From webhook-mailer at python.org Fri Dec 1 01:26:34 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 01 Dec 2017 06:26:34 -0000 Subject: [Python-checkins] bpo-32186: Release the GIL during lseek and fstat (GH-4652) (#4661) Message-ID: https://github.com/python/cpython/commit/8bcd41040a5f1f9b48a86d0e21f196e4b1f90e4b commit: 8bcd41040a5f1f9b48a86d0e21f196e4b1f90e4b branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Victor Stinner date: 2017-12-01T07:26:31+01:00 summary: bpo-32186: Release the GIL during lseek and fstat (GH-4652) (#4661) In _io_FileIO_readall_impl(), lseek() and _Py_fstat_noraise() were called without releasing the GIL. This can cause all threads to hang for unlimited time when calling FileIO.read() and the NFS server is not accessible. (cherry picked from commit 6a89481680b921e7b317c29877bdda9a6031e5ad) files: A Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst M Modules/_io/fileio.c diff --git a/Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst b/Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst new file mode 100644 index 00000000000..ea696c6098a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-30-20-38-16.bpo-32186.O42bVe.rst @@ -0,0 +1,3 @@ +io.FileIO.readall() and io.FileIO.read() now release the GIL when +getting the file size. Fixed hang of all threads with inaccessible NFS +server. Patch by Nir Soffer. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 918fa577758..52cbb94b24b 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -691,10 +691,12 @@ _io_FileIO_readall_impl(fileio *self) Py_ssize_t bytes_read = 0; Py_ssize_t n; size_t bufsize; + int fstat_result; if (self->fd < 0) return err_closed(); + Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS pos = _lseeki64(self->fd, 0L, SEEK_CUR); @@ -702,8 +704,10 @@ _io_FileIO_readall_impl(fileio *self) pos = lseek(self->fd, 0L, SEEK_CUR); #endif _Py_END_SUPPRESS_IPH + fstat_result = _Py_fstat_noraise(self->fd, &status); + Py_END_ALLOW_THREADS - if (_Py_fstat_noraise(self->fd, &status) == 0) + if (fstat_result == 0) end = status.st_size; else end = (Py_off_t)-1; From webhook-mailer at python.org Fri Dec 1 01:40:26 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 01 Dec 2017 06:40:26 -0000 Subject: [Python-checkins] Don't hide unexpected errors in PyErr_WarnExplicitObject(). (#4585) Message-ID: https://github.com/python/cpython/commit/a561862048555d555fa4850eaf832ae5474c7e1f commit: a561862048555d555fa4850eaf832ae5474c7e1f branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-01T08:40:23+02:00 summary: Don't hide unexpected errors in PyErr_WarnExplicitObject(). (#4585) files: M Python/ast.c diff --git a/Python/ast.c b/Python/ast.c index e44ce516617..e2092f0f854 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -4160,18 +4160,19 @@ warn_invalid_escape_sequence(struct compiling *c, const node *n, } if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, msg, c->c_filename, LINENO(n), - NULL, NULL) < 0 && - PyErr_ExceptionMatches(PyExc_DeprecationWarning)) + NULL, NULL) < 0) { - const char *s; + if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { + const char *s; - /* Replace the DeprecationWarning exception with a SyntaxError - to get a more accurate error report */ - PyErr_Clear(); + /* Replace the DeprecationWarning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); - s = PyUnicode_AsUTF8(msg); - if (s != NULL) { - ast_error(c, n, s); + s = PyUnicode_AsUTF8(msg); + if (s != NULL) { + ast_error(c, n, s); + } } Py_DECREF(msg); return -1; From webhook-mailer at python.org Fri Dec 1 02:08:52 2017 From: webhook-mailer at python.org (xdegaye) Date: Fri, 01 Dec 2017 07:08:52 -0000 Subject: [Python-checkins] bpo-28668: test.support.requires_multiprocessing_queue is removed (GH-4560) Message-ID: https://github.com/python/cpython/commit/bf2b65e413ca5ec705c7e2f463d0d75e947588a4 commit: bf2b65e413ca5ec705c7e2f463d0d75e947588a4 branch: master author: xdegaye committer: GitHub date: 2017-12-01T08:08:49+01:00 summary: bpo-28668: test.support.requires_multiprocessing_queue is removed (GH-4560) Skip tests with test.support.import_module('multiprocessing.synchronize') instead when the semaphore implementation is broken or missing. files: A Misc/NEWS.d/next/Tests/2017-11-25-14-53-29.bpo-28668.Y1G6pA.rst M Lib/test/support/__init__.py M Lib/test/test_logging.py diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index f0e15078d62..22868d4ba1a 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -87,8 +87,7 @@ "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute", "requires_IEEE_754", "skip_unless_xattr", "requires_zlib", "anticipate_failure", "load_package_tests", "detect_api_mismatch", - "check__all__", "requires_multiprocessing_queue", - "skip_unless_bind_unix_socket", + "check__all__", "skip_unless_bind_unix_socket", # sys "is_jython", "is_android", "check_impl_detail", "unix_shell", "setswitchinterval", @@ -1791,22 +1790,6 @@ def impl_detail(msg=None, **guards): msg = msg.format(' or '.join(guardnames)) return unittest.skip(msg) -_have_mp_queue = None -def requires_multiprocessing_queue(test): - """Skip decorator for tests that use multiprocessing.Queue.""" - global _have_mp_queue - if _have_mp_queue is None: - import multiprocessing - # Without a functioning shared semaphore implementation attempts to - # instantiate a Queue will result in an ImportError (issue #3770). - try: - multiprocessing.Queue() - _have_mp_queue = True - except ImportError: - _have_mp_queue = False - msg = "requires a functioning shared semaphore implementation" - return test if _have_mp_queue else unittest.skip(msg)(test) - def _parse_guards(guards): # Returns a tuple ({platform_name: run_me}, default_value) if not guards: diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 1968b4253c2..7101e3b1576 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3211,9 +3211,11 @@ def test_handle_called_with_queue_queue(self, mock_handle): self.assertEqual(mock_handle.call_count, 5 * self.repeat, 'correct number of handled log messages') - @support.requires_multiprocessing_queue @patch.object(logging.handlers.QueueListener, 'handle') def test_handle_called_with_mp_queue(self, mock_handle): + # Issue 28668: The multiprocessing (mp) module is not functional + # when the mp.synchronize module cannot be imported. + support.import_module('multiprocessing.synchronize') for i in range(self.repeat): log_queue = multiprocessing.Queue() self.setup_and_log(log_queue, '%s_%s' % (self.id(), i)) @@ -3230,7 +3232,6 @@ def get_all_from_queue(log_queue): except queue.Empty: return [] - @support.requires_multiprocessing_queue def test_no_messages_in_queue_after_stop(self): """ Five messages are logged then the QueueListener is stopped. This @@ -3238,6 +3239,9 @@ def test_no_messages_in_queue_after_stop(self): indicates that messages were not registered on the queue until _after_ the QueueListener stopped. """ + # Issue 28668: The multiprocessing (mp) module is not functional + # when the mp.synchronize module cannot be imported. + support.import_module('multiprocessing.synchronize') for i in range(self.repeat): queue = multiprocessing.Queue() self.setup_and_log(queue, '%s_%s' %(self.id(), i)) diff --git a/Misc/NEWS.d/next/Tests/2017-11-25-14-53-29.bpo-28668.Y1G6pA.rst b/Misc/NEWS.d/next/Tests/2017-11-25-14-53-29.bpo-28668.Y1G6pA.rst new file mode 100644 index 00000000000..e80516d984e --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-11-25-14-53-29.bpo-28668.Y1G6pA.rst @@ -0,0 +1,3 @@ +test.support.requires_multiprocessing_queue is removed. Skip tests with +test.support.import_module('multiprocessing.synchronize') instead when the +semaphore implementation is broken or missing. From webhook-mailer at python.org Fri Dec 1 02:21:47 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 01 Dec 2017 07:21:47 -0000 Subject: [Python-checkins] Don't hide unexpected errors in PyErr_WarnExplicitObject(). (GH-4585) (#4662) Message-ID: https://github.com/python/cpython/commit/9881e4e5386bf6a74b4a542321c23a7c396035ef commit: 9881e4e5386bf6a74b4a542321c23a7c396035ef branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-01T09:21:45+02:00 summary: Don't hide unexpected errors in PyErr_WarnExplicitObject(). (GH-4585) (#4662) (cherry picked from commit a561862048555d555fa4850eaf832ae5474c7e1f) files: M Python/ast.c diff --git a/Python/ast.c b/Python/ast.c index d2710259acb..ede7f4fd990 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -4136,18 +4136,19 @@ warn_invalid_escape_sequence(struct compiling *c, const node *n, } if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, msg, c->c_filename, LINENO(n), - NULL, NULL) < 0 && - PyErr_ExceptionMatches(PyExc_DeprecationWarning)) + NULL, NULL) < 0) { - const char *s; + if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { + const char *s; - /* Replace the DeprecationWarning exception with a SyntaxError - to get a more accurate error report */ - PyErr_Clear(); + /* Replace the DeprecationWarning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); - s = PyUnicode_AsUTF8(msg); - if (s != NULL) { - ast_error(c, n, s); + s = PyUnicode_AsUTF8(msg); + if (s != NULL) { + ast_error(c, n, s); + } } Py_DECREF(msg); return -1; From solipsis at pitrou.net Fri Dec 1 04:14:01 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 01 Dec 2017 09:14:01 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20171201091400.111000.2D15D4A46A1FEB47@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [2, 0, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloghJs4kf', '--timeout', '7200'] From webhook-mailer at python.org Fri Dec 1 07:33:48 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Fri, 01 Dec 2017 12:33:48 -0000 Subject: [Python-checkins] Fix asyncio.streams.FlowControlMixin docstring typo. (#4578) Message-ID: https://github.com/python/cpython/commit/8f5c28b19374df47ebe3d665e54c1dda5c2d7dca commit: 8f5c28b19374df47ebe3d665e54c1dda5c2d7dca branch: master author: John Chen committer: Andrew Svetlov date: 2017-12-01T14:33:40+02:00 summary: Fix asyncio.streams.FlowControlMixin docstring typo. (#4578) files: M Lib/asyncio/streams.py diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 05774e95300..15c9513527f 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -154,7 +154,7 @@ class FlowControlMixin(protocols.Protocol): """Reusable flow control logic for StreamWriter.drain(). This implements the protocol methods pause_writing(), - resume_reading() and connection_lost(). If the subclass overrides + resume_writing() and connection_lost(). If the subclass overrides these it must call the super methods. StreamWriter.drain() must wait for _drain_helper() coroutine. From webhook-mailer at python.org Fri Dec 1 12:27:12 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 01 Dec 2017 17:27:12 -0000 Subject: [Python-checkins] bpo-32030: Cleanup "path config" code (#4663) Message-ID: https://github.com/python/cpython/commit/b64de46aae148cfab0980e0ad478da7aafc44900 commit: b64de46aae148cfab0980e0ad478da7aafc44900 branch: master author: Victor Stinner committer: GitHub date: 2017-12-01T18:27:09+01:00 summary: bpo-32030: Cleanup "path config" code (#4663) * Rename PyPathConfig structure to _PyPathConfig and move it to Include/internal/pystate.h * Rename path_config to _Py_path_config * _PyPathConfig: Rename program_name field to program_full_path * Add assert(str != NULL); to _PyMem_RawWcsdup(), _PyMem_RawStrdup() and _PyMem_Strdup(). * Rename calculate_path() to pathconfig_global_init(). The function now does nothing if it's already initiallized. files: M Include/internal/pystate.h M Modules/getpath.c M Objects/obmalloc.c M PC/getpathp.c diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 7056e105ff7..50ad2fc83a3 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -37,6 +37,22 @@ struct _gilstate_runtime_state { #define _PyGILState_check_enabled _PyRuntime.gilstate.check_enabled +typedef struct { + /* Full path to the Python program */ + wchar_t *program_full_path; + wchar_t *prefix; +#ifdef MS_WINDOWS + wchar_t *dll_path; +#else + wchar_t *exec_prefix; +#endif + /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */ + wchar_t *module_search_path; +} _PyPathConfig; + +#define _PyPathConfig_INIT {.module_search_path = NULL} + + /* Full Python runtime state */ typedef struct pyruntimestate { diff --git a/Modules/getpath.c b/Modules/getpath.c index 02d626cea73..9f5e8b3ff5c 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -1,6 +1,7 @@ /* Return the initial module search path. */ #include "Python.h" +#include "internal/pystate.h" #include "osdefs.h" #include @@ -114,14 +115,6 @@ extern "C" { ? _Py_INIT_USER_ERR("cannot decode " #NAME) \ : _Py_INIT_NO_MEMORY() - -typedef struct { - wchar_t *prefix; - wchar_t *exec_prefix; - wchar_t *program_name; - wchar_t *module_search_path; -} PyPathConfig; - typedef struct { wchar_t *path_env; /* PATH environment variable */ wchar_t *home; /* PYTHONHOME environment variable */ @@ -142,7 +135,7 @@ typedef struct { static const wchar_t delimiter[2] = {DELIM, '\0'}; static const wchar_t separator[2] = {SEP, '\0'}; -static PyPathConfig path_config = {.module_search_path = NULL}; +static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; /* Get file status. Encode the path to the locale encoding. */ @@ -592,10 +585,10 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static _PyInitError -calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) +calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) { - wchar_t program_name[MAXPATHLEN+1]; - memset(program_name, 0, sizeof(program_name)); + wchar_t program_full_path[MAXPATHLEN+1]; + memset(program_full_path, 0, sizeof(program_full_path)); #ifdef __APPLE__ #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 @@ -612,7 +605,7 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) * $PATH isn't exported, you lose. */ if (wcschr(calculate->program_name, SEP)) { - wcsncpy(program_name, calculate->program_name, MAXPATHLEN); + wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -628,10 +621,10 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { - size_t r = mbstowcs(program_name, execpath, MAXPATHLEN+1); + size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1); if (r == (size_t)-1 || r > MAXPATHLEN) { /* Could not convert execpath, or it's too long. */ - program_name[0] = '\0'; + program_full_path[0] = '\0'; } } #endif /* __APPLE__ */ @@ -645,34 +638,34 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) if (len > MAXPATHLEN) { len = MAXPATHLEN; } - wcsncpy(program_name, path, len); - program_name[len] = '\0'; + wcsncpy(program_full_path, path, len); + program_full_path[len] = '\0'; } else { - wcsncpy(program_name, path, MAXPATHLEN); + wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_name, calculate->program_name); - if (isxfile(program_name)) { + joinpath(program_full_path, calculate->program_name); + if (isxfile(program_full_path)) { break; } if (!delim) { - program_name[0] = L'\0'; + program_full_path[0] = L'\0'; break; } path = delim + 1; } } else { - program_name[0] = '\0'; + program_full_path[0] = '\0'; } - if (program_name[0] != SEP && program_name[0] != '\0') { - absolutize(program_name); + if (program_full_path[0] != SEP && program_full_path[0] != '\0') { + absolutize(program_full_path); } - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { + config->program_full_path = _PyMem_RawWcsdup(program_full_path); + if (config->program_full_path == NULL) { return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -680,9 +673,9 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) static _PyInitError -calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) +calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path) { - wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN); + wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN); calculate->argv0_path[MAXPATHLEN] = '\0'; #ifdef WITH_NEXT_FRAMEWORK @@ -718,10 +711,10 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) if (!ismodule(calculate->argv0_path)) { /* We are in the build directory so use the name of the executable - we know that the absolute path is passed */ - wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN); + wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN); } else { - /* Use the location of the library as the program_name */ + /* Use the location of the library as the program_full_path */ wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN); } PyMem_RawFree(wbuf); @@ -730,7 +723,7 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) #if HAVE_READLINK wchar_t tmpbuffer[MAXPATHLEN+1]; - int linklen = _Py_wreadlink(program_name, tmpbuffer, MAXPATHLEN); + int linklen = _Py_wreadlink(program_full_path, tmpbuffer, MAXPATHLEN); while (linklen != -1) { if (tmpbuffer[0] == SEP) { /* tmpbuffer should never be longer than MAXPATHLEN, @@ -738,7 +731,7 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) wcsncpy(calculate->argv0_path, tmpbuffer, MAXPATHLEN); } else { - /* Interpret relative to program_name */ + /* Interpret relative to program_full_path */ reduce(calculate->argv0_path); joinpath(calculate->argv0_path, tmpbuffer); } @@ -819,7 +812,7 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) static _PyInitError calculate_module_search_path(PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, - PyPathConfig *config) + _PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; @@ -955,14 +948,14 @@ calculate_free(PyCalculatePath *calculate) static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config) +calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) { - _PyInitError err = calculate_program_name(calculate, config); + _PyInitError err = calculate_program_full_path(calculate, config); if (_Py_INIT_FAILED(err)) { return err; } - err = calculate_argv0_path(calculate, config->program_name); + err = calculate_argv0_path(calculate, config->program_full_path); if (_Py_INIT_FAILED(err)) { return err; } @@ -1011,7 +1004,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config) static void -pathconfig_clear(PyPathConfig *config) +pathconfig_clear(_PyPathConfig *config) { #define CLEAR(ATTR) \ do { \ @@ -1021,7 +1014,7 @@ pathconfig_clear(PyPathConfig *config) CLEAR(config->prefix); CLEAR(config->exec_prefix); - CLEAR(config->program_name); + CLEAR(config->program_full_path); CLEAR(config->module_search_path); #undef CLEAR } @@ -1032,7 +1025,7 @@ pathconfig_clear(PyPathConfig *config) _PyInitError _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) { - if (path_config.module_search_path) { + if (_Py_path_config.module_search_path) { /* Already initialized */ return _Py_INIT_OK(); } @@ -1045,7 +1038,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - PyPathConfig new_path_config; + _PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); err = calculate_path_impl(&calculate, &new_path_config); @@ -1054,7 +1047,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - path_config = new_path_config; + _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: @@ -1064,8 +1057,13 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) static void -calculate_path(void) +pathconfig_global_init(void) { + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + _PyInitError err; _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; @@ -1084,7 +1082,7 @@ calculate_path(void) void _PyPathConfig_Fini(void) { - pathconfig_clear(&path_config); + pathconfig_clear(&_Py_path_config); } @@ -1093,58 +1091,50 @@ void Py_SetPath(const wchar_t *path) { if (path == NULL) { - pathconfig_clear(&path_config); + pathconfig_clear(&_Py_path_config); return; } - PyPathConfig new_config; - new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + _PyPathConfig new_config; + new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); new_config.exec_prefix = _PyMem_RawWcsdup(L""); new_config.prefix = _PyMem_RawWcsdup(L""); new_config.module_search_path = _PyMem_RawWcsdup(path); - pathconfig_clear(&path_config); - path_config = new_config; + pathconfig_clear(&_Py_path_config); + _Py_path_config = new_config; } wchar_t * Py_GetPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.module_search_path; + pathconfig_global_init(); + return _Py_path_config.module_search_path; } wchar_t * Py_GetPrefix(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.prefix; + pathconfig_global_init(); + return _Py_path_config.prefix; } wchar_t * Py_GetExecPrefix(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.exec_prefix; + pathconfig_global_init(); + return _Py_path_config.exec_prefix; } wchar_t * Py_GetProgramFullPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.program_name; + pathconfig_global_init(); + return _Py_path_config.program_full_path; } #ifdef __cplusplus diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 4d85f0c368b..7911028ad83 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -564,6 +564,8 @@ PyMem_Free(void *ptr) wchar_t* _PyMem_RawWcsdup(const wchar_t *str) { + assert(str != NULL); + size_t len = wcslen(str); if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) { return NULL; @@ -582,13 +584,12 @@ _PyMem_RawWcsdup(const wchar_t *str) char * _PyMem_RawStrdup(const char *str) { - size_t size; - char *copy; - - size = strlen(str) + 1; - copy = PyMem_RawMalloc(size); - if (copy == NULL) + assert(str != NULL); + size_t size = strlen(str) + 1; + char *copy = PyMem_RawMalloc(size); + if (copy == NULL) { return NULL; + } memcpy(copy, str, size); return copy; } @@ -596,13 +597,12 @@ _PyMem_RawStrdup(const char *str) char * _PyMem_Strdup(const char *str) { - size_t size; - char *copy; - - size = strlen(str) + 1; - copy = PyMem_Malloc(size); - if (copy == NULL) + assert(str != NULL); + size_t size = strlen(str) + 1; + char *copy = PyMem_Malloc(size); + if (copy == NULL) { return NULL; + } memcpy(copy, str, size); return copy; } diff --git a/PC/getpathp.c b/PC/getpathp.c index fe0226ba5d2..ad04b6b6efc 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -80,6 +80,7 @@ #include "Python.h" +#include "internal/pystate.h" #include "osdefs.h" #include @@ -116,13 +117,6 @@ #define LANDMARK L"lib\\os.py" #endif -typedef struct { - wchar_t *prefix; - wchar_t *program_name; - wchar_t *dll_path; - wchar_t *module_search_path; -} PyPathConfig; - typedef struct { wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ wchar_t *path_env; /* PATH environment variable */ @@ -138,7 +132,7 @@ typedef struct { } PyCalculatePath; -static PyPathConfig path_config = {.module_search_path = NULL}; +static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; /* determine if "ch" is a separator character */ @@ -295,7 +289,7 @@ gotlandmark(wchar_t *prefix, const wchar_t *landmark) /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. - assumption provided by only caller, calculate_path() */ + assumption provided by only caller, calculate_path_impl() */ static int search_for_prefix(wchar_t *prefix, wchar_t *argv0_path, const wchar_t *landmark) { @@ -484,7 +478,7 @@ getpythonregpath(HKEY keyBase, int skipcore) static _PyInitError -get_dll_path(PyCalculatePath *calculate, PyPathConfig *config) +get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t dll_path[MAXPATHLEN+1]; memset(dll_path, 0, sizeof(dll_path)); @@ -509,12 +503,12 @@ get_dll_path(PyCalculatePath *calculate, PyPathConfig *config) static _PyInitError -get_program_name(PyCalculatePath *calculate, PyPathConfig *config) +get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) { - wchar_t program_name[MAXPATHLEN+1]; - memset(program_name, 0, sizeof(program_name)); + wchar_t program_full_path[MAXPATHLEN+1]; + memset(program_full_path, 0, sizeof(program_full_path)); - if (GetModuleFileNameW(NULL, program_name, MAXPATHLEN)) { + if (GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { goto done; } @@ -529,7 +523,7 @@ get_program_name(PyCalculatePath *calculate, PyPathConfig *config) if (wcschr(calculate->program_name, SEP)) #endif { - wcsncpy(program_name, calculate->program_name, MAXPATHLEN); + wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); } else if (calculate->path_env) { wchar_t *path = calculate->path_env; @@ -540,33 +534,33 @@ get_program_name(PyCalculatePath *calculate, PyPathConfig *config) size_t len = delim - path; /* ensure we can't overwrite buffer */ len = min(MAXPATHLEN,len); - wcsncpy(program_name, path, len); - program_name[len] = '\0'; + wcsncpy(program_full_path, path, len); + program_full_path[len] = '\0'; } else { - wcsncpy(program_name, path, MAXPATHLEN); + wcsncpy(program_full_path, path, MAXPATHLEN); } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_name, calculate->program_name); - if (exists(program_name)) { + join(program_full_path, calculate->program_name); + if (exists(program_full_path)) { break; } if (!delim) { - program_name[0] = '\0'; + program_full_path[0] = '\0'; break; } path = delim + 1; } } else { - program_name[0] = '\0'; + program_full_path[0] = '\0'; } done: - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { + config->program_full_path = _PyMem_RawWcsdup(program_full_path); + if (config->program_full_path == NULL) { return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -626,7 +620,7 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) static int -read_pth_file(PyPathConfig *config, wchar_t *prefix, const wchar_t *path, +read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path, int *isolated, int *nosite) { FILE *sp_file = _Py_wfopen(path, L"r"); @@ -727,15 +721,15 @@ calculate_init(PyCalculatePath *calculate, static int -get_pth_filename(wchar_t *spbuffer, PyPathConfig *config) +get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) { if (config->dll_path[0]) { if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) { return 1; } } - if (config->program_name[0]) { - if (!change_ext(spbuffer, config->program_name, L"._pth") && exists(spbuffer)) { + if (config->program_full_path[0]) { + if (!change_ext(spbuffer, config->program_full_path, L"._pth") && exists(spbuffer)) { return 1; } } @@ -744,7 +738,7 @@ get_pth_filename(wchar_t *spbuffer, PyPathConfig *config) static int -calculate_pth_file(PyPathConfig *config, wchar_t *prefix) +calculate_pth_file(_PyPathConfig *config, wchar_t *prefix) { wchar_t spbuffer[MAXPATHLEN+1]; @@ -821,7 +815,7 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) static _PyInitError -calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config, wchar_t *prefix) +calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) { int skiphome = calculate->home==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED @@ -1002,7 +996,7 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config, w static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, +calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, const _PyMainInterpreterConfig *main_config) { _PyInitError err; @@ -1012,13 +1006,13 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, return err; } - err = get_program_name(calculate, config); + err = get_program_full_path(calculate, config); if (_Py_INIT_FAILED(err)) { return err; } - /* program_name guaranteed \0 terminated in MAXPATH+1 bytes. */ - wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_name); + /* program_full_path guaranteed \0 terminated in MAXPATH+1 bytes. */ + wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_full_path); reduce(calculate->argv0_path); wchar_t prefix[MAXPATHLEN+1]; @@ -1033,7 +1027,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, /* Calculate zip archive path from DLL or exe path */ change_ext(calculate->zip_path, - config->dll_path[0] ? config->dll_path : config->program_name, + config->dll_path[0] ? config->dll_path : config->program_full_path, L".zip"); calculate_home_prefix(calculate, prefix); @@ -1062,7 +1056,7 @@ calculate_free(PyCalculatePath *calculate) static void -pathconfig_clear(PyPathConfig *config) +pathconfig_clear(_PyPathConfig *config) { #define CLEAR(ATTR) \ do { \ @@ -1071,7 +1065,7 @@ pathconfig_clear(PyPathConfig *config) } while (0) CLEAR(config->prefix); - CLEAR(config->program_name); + CLEAR(config->program_full_path); CLEAR(config->dll_path); CLEAR(config->module_search_path); #undef CLEAR @@ -1083,7 +1077,7 @@ pathconfig_clear(PyPathConfig *config) _PyInitError _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) { - if (path_config.module_search_path) { + if (_Py_path_config.module_search_path) { /* Already initialized */ return _Py_INIT_OK(); } @@ -1095,7 +1089,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) calculate_init(&calculate, main_config); - PyPathConfig new_path_config; + _PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); err = calculate_path_impl(&calculate, &new_path_config, main_config); @@ -1103,7 +1097,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - path_config = new_path_config; + _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: @@ -1116,8 +1110,13 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) static void -calculate_path(void) +pathconfig_global_init(void) { + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + _PyInitError err; _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; @@ -1136,7 +1135,7 @@ calculate_path(void) void _PyPathConfig_Fini(void) { - pathconfig_clear(&path_config); + pathconfig_clear(&_Py_path_config); } @@ -1145,42 +1144,38 @@ _PyPathConfig_Fini(void) void Py_SetPath(const wchar_t *path) { - if (path_config.module_search_path != NULL) { - pathconfig_clear(&path_config); + if (_Py_path_config.module_search_path != NULL) { + pathconfig_clear(&_Py_path_config); } if (path == NULL) { return; } - PyPathConfig new_config; - new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + _PyPathConfig new_config; + new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); new_config.prefix = _PyMem_RawWcsdup(L""); new_config.dll_path = _PyMem_RawWcsdup(L""); new_config.module_search_path = _PyMem_RawWcsdup(path); - pathconfig_clear(&path_config); - path_config = new_config; + pathconfig_clear(&_Py_path_config); + _Py_path_config = new_config; } wchar_t * Py_GetPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.module_search_path; + pathconfig_global_init(); + return _Py_path_config.module_search_path; } wchar_t * Py_GetPrefix(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.prefix; + pathconfig_global_init(); + return _Py_path_config.prefix; } @@ -1194,10 +1189,8 @@ Py_GetExecPrefix(void) wchar_t * Py_GetProgramFullPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.program_name; + pathconfig_global_init(); + return _Py_path_config.program_full_path; } @@ -1221,7 +1214,7 @@ _Py_CheckPython3() /* If there is a python3.dll next to the python3y.dll, assume this is a build tree; use that DLL */ - wcscpy(py3path, path_config.dll_path); + wcscpy(py3path, _Py_path_config.dll_path); s = wcsrchr(py3path, L'\\'); if (!s) { s = py3path; From webhook-mailer at python.org Fri Dec 1 13:30:46 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 01 Dec 2017 18:30:46 -0000 Subject: [Python-checkins] bpo-32030: Fix Py_GetPath(): init program_name (#4665) Message-ID: https://github.com/python/cpython/commit/9ac3d8882712c9675c3d2f9f84af6b5729575cde commit: 9ac3d8882712c9675c3d2f9f84af6b5729575cde branch: master author: Victor Stinner committer: GitHub date: 2017-12-01T19:30:41+01:00 summary: bpo-32030: Fix Py_GetPath(): init program_name (#4665) * _PyMainInterpreterConfig_ReadEnv() now sets program_name from environment variables and pymain_parse_envvars() implements the falls back on argv[0]. * Remove _PyMain.program_name: use the program_name from _PyMainInterpreterConfig * Move the Py_SetProgramName() call back to pymain_init_python(), just before _Py_InitializeCore(). * pathconfig_global_init() now also calls _PyMainInterpreterConfig_Read() to set program_name if it isn't set yet * Cleanup PyCalculatePath: pass main_config to subfunctions to get directly fields from main_config (home, module_search_path_env and program_name) files: M Modules/getpath.c M Modules/main.c M PC/getpathp.c diff --git a/Modules/getpath.c b/Modules/getpath.c index 9f5e8b3ff5c..183717d8171 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -117,10 +117,7 @@ extern "C" { typedef struct { wchar_t *path_env; /* PATH environment variable */ - wchar_t *home; /* PYTHONHOME environment variable */ - wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ - wchar_t *program_name; /* Program name */ wchar_t *pythonpath; /* PYTHONPATH define */ wchar_t *prefix; /* PREFIX define */ wchar_t *exec_prefix; /* EXEC_PREFIX define */ @@ -360,14 +357,15 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) bytes long. */ static int -search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix) +search_for_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *prefix) { size_t n; wchar_t *vpath; /* If PYTHONHOME is set, we believe it unconditionally */ - if (calculate->home) { - wcsncpy(prefix, calculate->home, MAXPATHLEN); + if (main_config->home) { + wcsncpy(prefix, main_config->home, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; wchar_t *delim = wcschr(prefix, DELIM); if (delim) { @@ -426,9 +424,10 @@ search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix) static void -calculate_prefix(PyCalculatePath *calculate, wchar_t *prefix) +calculate_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *prefix) { - calculate->prefix_found = search_for_prefix(calculate, prefix); + calculate->prefix_found = search_for_prefix(main_config, calculate, prefix); if (!calculate->prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -470,18 +469,19 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) MAXPATHLEN bytes long. */ static int -search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) +search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *exec_prefix) { size_t n; /* If PYTHONHOME is set, we believe it unconditionally */ - if (calculate->home) { - wchar_t *delim = wcschr(calculate->home, DELIM); + if (main_config->home) { + wchar_t *delim = wcschr(main_config->home, DELIM); if (delim) { wcsncpy(exec_prefix, delim+1, MAXPATHLEN); } else { - wcsncpy(exec_prefix, calculate->home, MAXPATHLEN); + wcsncpy(exec_prefix, main_config->home, MAXPATHLEN); } exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, calculate->lib_python); @@ -552,9 +552,12 @@ search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static void -calculate_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) +calculate_exec_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *exec_prefix) { - calculate->exec_prefix_found = search_for_exec_prefix(calculate, exec_prefix); + calculate->exec_prefix_found = search_for_exec_prefix(main_config, + calculate, + exec_prefix); if (!calculate->exec_prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -585,7 +588,8 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static _PyInitError -calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) +calculate_program_full_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); @@ -604,8 +608,8 @@ calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) * other way to find a directory to start the search from. If * $PATH isn't exported, you lose. */ - if (wcschr(calculate->program_name, SEP)) { - wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); + if (wcschr(main_config->program_name, SEP)) { + wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -645,7 +649,7 @@ calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_full_path, calculate->program_name); + joinpath(program_full_path, main_config->program_name); if (isxfile(program_full_path)) { break; } @@ -810,14 +814,15 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) static _PyInitError -calculate_module_search_path(PyCalculatePath *calculate, +calculate_module_search_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, _PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; - if (calculate->module_search_path_env != NULL) { - bufsz += wcslen(calculate->module_search_path_env) + 1; + if (main_config->module_search_path_env != NULL) { + bufsz += wcslen(main_config->module_search_path_env) + 1; } wchar_t *defpath = calculate->pythonpath; @@ -851,8 +856,8 @@ calculate_module_search_path(PyCalculatePath *calculate, buf[0] = '\0'; /* Run-time value of $PYTHONPATH goes first */ - if (calculate->module_search_path_env) { - wcscpy(buf, calculate->module_search_path_env); + if (main_config->module_search_path_env) { + wcscpy(buf, main_config->module_search_path_env); wcscat(buf, delimiter); } @@ -903,10 +908,6 @@ static _PyInitError calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) { - calculate->home = main_config->home; - calculate->module_search_path_env = main_config->module_search_path_env; - calculate->program_name = main_config->program_name; - size_t len; char *path = getenv("PATH"); if (path) { @@ -948,9 +949,12 @@ calculate_free(PyCalculatePath *calculate) static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) +calculate_path_impl(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { - _PyInitError err = calculate_program_full_path(calculate, config); + _PyInitError err; + + err = calculate_program_full_path(main_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -964,13 +968,13 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); - calculate_prefix(calculate, prefix); + calculate_prefix(main_config, calculate, prefix); calculate_zip_path(calculate, prefix); wchar_t exec_prefix[MAXPATHLEN+1]; memset(exec_prefix, 0, sizeof(exec_prefix)); - calculate_exec_prefix(calculate, exec_prefix); + calculate_exec_prefix(main_config, calculate, exec_prefix); if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !Py_FrozenFlag) @@ -979,8 +983,8 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) "Consider setting $PYTHONHOME to [:]\n"); } - err = calculate_module_search_path(calculate, prefix, exec_prefix, - config); + err = calculate_module_search_path(main_config, calculate, + prefix, exec_prefix, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1041,7 +1045,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) _PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); - err = calculate_path_impl(&calculate, &new_path_config); + err = calculate_path_impl(main_config, &calculate, &new_path_config); if (_Py_INIT_FAILED(err)) { pathconfig_clear(&new_path_config); goto done; @@ -1068,14 +1072,26 @@ pathconfig_global_init(void) _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; err = _PyMainInterpreterConfig_ReadEnv(&config); - if (!_Py_INIT_FAILED(err)) { - err = _PyPathConfig_Init(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + err = _PyMainInterpreterConfig_Read(&config); + if (_Py_INIT_FAILED(err)) { + goto error; } - _PyMainInterpreterConfig_Clear(&config); + err = _PyPathConfig_Init(&config); if (_Py_INIT_FAILED(err)) { - _Py_FatalInitError(err); + goto error; } + + _PyMainInterpreterConfig_Clear(&config); + return; + +error: + _PyMainInterpreterConfig_Clear(&config); + _Py_FatalInitError(err); } diff --git a/Modules/main.c b/Modules/main.c index e9d524a1463..caec97f8642 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -412,7 +412,6 @@ typedef struct { /* non-zero if filename, command (-c) or module (-m) is set on the command line */ int run_code; - wchar_t *program_name; /* Error message if a function failed */ _PyInitError err; /* PYTHONWARNINGS env var */ @@ -429,7 +428,6 @@ typedef struct { .config = _PyMainInterpreterConfig_INIT, \ .main_importer_path = NULL, \ .run_code = -1, \ - .program_name = NULL, \ .err = _Py_INIT_OK(), \ .env_warning_options = {0, NULL}} @@ -455,7 +453,6 @@ pymain_free_impl(_PyMain *pymain) pymain_optlist_clear(&pymain->env_warning_options); Py_CLEAR(pymain->main_importer_path); - PyMem_RawFree(pymain->program_name); _PyMainInterpreterConfig_Clear(&pymain->config); @@ -874,14 +871,11 @@ pymain_init_stdio(_PyMain *pymain) /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ - environment variables on macOS if available, use argv[0] by default. - - Return 0 on success. - Set pymain->err and return -1 on error. */ -static int -pymain_get_program_name(_PyMain *pymain) + environment variables on macOS if available. */ +static _PyInitError +config_get_program_name(_PyMainInterpreterConfig *config) { - assert(pymain->program_name == NULL); + assert(config->program_name == NULL); #ifdef __APPLE__ char *p; /* On MacOS X, when the Python interpreter is embedded in an @@ -899,12 +893,11 @@ pymain_get_program_name(_PyMain *pymain) buffer = PyMem_RawMalloc(len * sizeof(wchar_t)); if (buffer == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + return _Py_INIT_NO_MEMORY(); } mbstowcs(buffer, p, len); - pymain->program_name = buffer; + pymain->config.program_name = buffer; } #ifdef WITH_NEXT_FRAMEWORK else { @@ -916,19 +909,26 @@ pymain_get_program_name(_PyMain *pymain) size_t len; wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len); if (wbuf == NULL) { - SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len); - return -1; + return SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len); } - pymain->program_name = wbuf; + pymain->config.program_name = wbuf; } } #endif /* WITH_NEXT_FRAMEWORK */ #endif /* __APPLE__ */ + return _Py_INIT_OK(); +} - if (pymain->program_name == NULL) { + +/* If config_get_program_name() found no program name: use argv[0] by default. + Return 0 on success. Set pymain->err and return -1 on error. */ +static int +pymain_get_program_name(_PyMain *pymain) +{ + if (pymain->config.program_name == NULL) { /* Use argv[0] by default */ - pymain->program_name = pymain_wstrdup(pymain, pymain->argv[0]); - if (pymain->program_name == NULL) { + pymain->config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); + if (pymain->config.program_name == NULL) { return -1; } } @@ -1451,11 +1451,9 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) return err; } - /* FIXME: _PyMainInterpreterConfig_Read() has the same code. Remove it - here? See also pymain_get_program_name() and pymain_parse_envvars(). */ - config->program_name = _PyMem_RawWcsdup(Py_GetProgramName()); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); + err = config_get_program_name(config); + if (_Py_INIT_FAILED(err)) { + return err; } return _Py_INIT_OK(); @@ -1481,25 +1479,17 @@ pymain_parse_envvars(_PyMain *pymain) if (pymain_warnings_envvar(pymain) < 0) { return -1; } - if (pymain_get_program_name(pymain) < 0) { - return -1; - } - core_config->allocator = Py_GETENV("PYTHONMALLOC"); - - /* FIXME: move pymain_get_program_name() code into - _PyMainInterpreterConfig_ReadEnv(). - Problem: _PyMainInterpreterConfig_ReadEnv() doesn't have access - to argv[0]. */ - Py_SetProgramName(pymain->program_name); - /* Don't free program_name here: the argument to Py_SetProgramName - must remain valid until Py_FinalizeEx is called. The string is freed - by pymain_free(). */ _PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config); if (_Py_INIT_FAILED(pymain->err)) { pymain->err = err; return -1; } + if (pymain_get_program_name(pymain) < 0) { + return -1; + } + + core_config->allocator = Py_GETENV("PYTHONMALLOC"); /* -X options */ if (pymain_get_xoption(pymain, L"showrefcount")) { @@ -1578,6 +1568,11 @@ pymain_init_python(_PyMain *pymain) { pymain_init_stdio(pymain); + Py_SetProgramName(pymain->config.program_name); + /* Don't free program_name here: the argument to Py_SetProgramName + must remain valid until Py_FinalizeEx is called. The string is freed + by pymain_free(). */ + pymain->err = _Py_InitializeCore(&pymain->core_config); if (_Py_INIT_FAILED(pymain->err)) { return -1; diff --git a/PC/getpathp.c b/PC/getpathp.c index ad04b6b6efc..89d37a84133 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -118,7 +118,6 @@ #endif typedef struct { - wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ wchar_t *path_env; /* PATH environment variable */ wchar_t *home; /* PYTHONHOME environment variable */ @@ -126,7 +125,6 @@ typedef struct { wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */ wchar_t *user_path; /* from HKEY_CURRENT_USER */ - wchar_t *program_name; /* Program name */ wchar_t argv0_path[MAXPATHLEN+1]; wchar_t zip_path[MAXPATHLEN+1]; } PyCalculatePath; @@ -503,7 +501,8 @@ get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) static _PyInitError -get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) +get_program_full_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); @@ -518,12 +517,13 @@ get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) * $PATH isn't exported, you lose. */ #ifdef ALTSEP - if (wcschr(calculate->program_name, SEP) || wcschr(calculate->program_name, ALTSEP)) + if (wcschr(main_config->program_name, SEP) || + wcschr(main_config->program_name, ALTSEP)) #else - if (wcschr(calculate->program_name, SEP)) + if (wcschr(main_config->program_name, SEP)) #endif { - wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); + wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); } else if (calculate->path_env) { wchar_t *path = calculate->path_env; @@ -542,7 +542,7 @@ get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, calculate->program_name); + join(program_full_path, main_config->program_name); if (exists(program_full_path)) { break; } @@ -713,9 +713,6 @@ calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) { calculate->home = main_config->home; - calculate->module_search_path_env = main_config->module_search_path_env; - calculate->program_name = main_config->program_name; - calculate->path_env = _wgetenv(L"PATH"); } @@ -815,7 +812,9 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) static _PyInitError -calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) +calculate_module_search_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config, + wchar_t *prefix) { int skiphome = calculate->home==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED @@ -824,7 +823,7 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (calculate->module_search_path_env!=NULL || calculate->home!=NULL || \ + int skipdefault = (main_config->module_search_path_env!=NULL || calculate->home!=NULL || \ calculate->machine_path!=NULL || calculate->user_path!=NULL); /* We need to construct a path from the following parts. @@ -861,8 +860,8 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, bufsz += wcslen(calculate->machine_path) + 1; } bufsz += wcslen(calculate->zip_path) + 1; - if (calculate->module_search_path_env != NULL) { - bufsz += wcslen(calculate->module_search_path_env) + 1; + if (main_config->module_search_path_env != NULL) { + bufsz += wcslen(main_config->module_search_path_env) + 1; } wchar_t *buf, *start_buf; @@ -870,9 +869,9 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, if (buf == NULL) { /* We can't exit, so print a warning and limp along */ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); - if (calculate->module_search_path_env) { + if (main_config->module_search_path_env) { fprintf(stderr, "Using environment $PYTHONPATH.\n"); - config->module_search_path = calculate->module_search_path_env; + config->module_search_path = main_config->module_search_path_env; } else { fprintf(stderr, "Using default static path.\n"); @@ -882,8 +881,8 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, } start_buf = buf; - if (calculate->module_search_path_env) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->module_search_path_env)) { + if (main_config->module_search_path_env) { + if (wcscpy_s(buf, bufsz - (buf - start_buf), main_config->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -996,8 +995,8 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +calculate_path_impl(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { _PyInitError err; @@ -1006,7 +1005,7 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, return err; } - err = get_program_full_path(calculate, config); + err = get_program_full_path(main_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1032,7 +1031,7 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, calculate_home_prefix(calculate, prefix); - err = calculate_module_search_path(calculate, config, prefix); + err = calculate_module_search_path(main_config, calculate, config, prefix); if (_Py_INIT_FAILED(err)) { return err; } @@ -1092,7 +1091,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) _PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); - err = calculate_path_impl(&calculate, &new_path_config, main_config); + err = calculate_path_impl(main_config, &calculate, &new_path_config); if (_Py_INIT_FAILED(err)) { goto done; } @@ -1121,14 +1120,26 @@ pathconfig_global_init(void) _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; err = _PyMainInterpreterConfig_ReadEnv(&config); - if (!_Py_INIT_FAILED(err)) { - err = _PyPathConfig_Init(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + err = _PyMainInterpreterConfig_Read(&config); + if (_Py_INIT_FAILED(err)) { + goto error; } - _PyMainInterpreterConfig_Clear(&config); + err = _PyPathConfig_Init(&config); if (_Py_INIT_FAILED(err)) { - _Py_FatalInitError(err); + goto error; } + + _PyMainInterpreterConfig_Clear(&config); + return; + +error: + _PyMainInterpreterConfig_Clear(&config); + _Py_FatalInitError(err); } From webhook-mailer at python.org Fri Dec 1 14:09:58 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 01 Dec 2017 19:09:58 -0000 Subject: [Python-checkins] bpo-32030: Don't call _PyPathConfig_Fini() in Py_FinalizeEx() (#4667) Message-ID: https://github.com/python/cpython/commit/ebac19dad6263141d5db0a2c923efe049dba99d2 commit: ebac19dad6263141d5db0a2c923efe049dba99d2 branch: master author: Victor Stinner committer: GitHub date: 2017-12-01T20:09:52+01:00 summary: bpo-32030: Don't call _PyPathConfig_Fini() in Py_FinalizeEx() (#4667) Changes: * _PyPathConfig_Fini() cannot be called in Py_FinalizeEx(). Py_Initialize() and Py_Finalize() can be called multiple times, but it must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or Py_SetPythonHome(), whereas _PyPathConfig_Fini() clear all these parameters. * config_get_program_name() and calculate_program_full_path() now also decode paths using Py_DecodeLocale() to use the surrogateescape error handler, rather than decoding using mbstowcs() which is strict. * Change _Py_CheckPython3() prototype: () => (void) * Truncate a few lines which were too long files: M Include/pylifecycle.h M Modules/getpath.c M Modules/main.c M PC/getpathp.c M Python/pylifecycle.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index d32c98b6985..3db88326aee 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -109,7 +109,7 @@ PyAPI_FUNC(void) _PyPathConfig_Fini(void); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS -int _Py_CheckPython3(); +int _Py_CheckPython3(void); #endif /* In their own files */ diff --git a/Modules/getpath.c b/Modules/getpath.c index 183717d8171..235badab230 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -625,11 +625,13 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { - size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1); - if (r == (size_t)-1 || r > MAXPATHLEN) { - /* Could not convert execpath, or it's too long. */ - program_full_path[0] = '\0'; + size_t len; + wchar_t *path = Py_DecodeLocale(execpath, &len); + if (path == NULL) { + return DECODE_LOCALE_ERR("executable path", len); } + wcsncpy(program_full_path, path, MAXPATHLEN); + PyMem_RawFree(path); } #endif /* __APPLE__ */ else if (calculate->path_env) { diff --git a/Modules/main.c b/Modules/main.c index caec97f8642..4659c5d670b 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -888,15 +888,12 @@ config_get_program_name(_PyMainInterpreterConfig *config) See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') { - wchar_t* buffer; - size_t len = strlen(p) + 1; - - buffer = PyMem_RawMalloc(len * sizeof(wchar_t)); - if (buffer == NULL) { - return _Py_INIT_NO_MEMORY(); + size_t len; + wchar_t* program_name = Py_DecodeLocale(p, &len); + if (program_name == NULL) { + return SET_DECODE_ERROR("PYTHONEXECUTABLE environment " + "variable", len); } - - mbstowcs(buffer, p, len); pymain->config.program_name = buffer; } #ifdef WITH_NEXT_FRAMEWORK @@ -907,11 +904,12 @@ config_get_program_name(_PyMainInterpreterConfig *config) * the argv0 of the stub executable */ size_t len; - wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len); - if (wbuf == NULL) { - return SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len); + wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len); + if (program_name == NULL) { + return SET_DECODE_ERROR("__PYVENV_LAUNCHER__ environment " + "variable", len); } - pymain->config.program_name = wbuf; + pymain->config.program_name = program_name; } } #endif /* WITH_NEXT_FRAMEWORK */ @@ -1666,6 +1664,14 @@ pymain_impl(_PyMain *pymain) other special meaning */ pymain->status = 120; } + + /* _PyPathConfig_Fini() cannot be called in Py_FinalizeEx(). + Py_Initialize() and Py_Finalize() can be called multiple times, but it + must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or + Py_SetPythonHome(), whereas _PyPathConfig_Fini() clear all these + parameters. */ + _PyPathConfig_Fini(); + return 0; } diff --git a/PC/getpathp.c b/PC/getpathp.c index 89d37a84133..f8cfd7e6978 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -721,12 +721,16 @@ static int get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) { if (config->dll_path[0]) { - if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) { + if (!change_ext(spbuffer, config->dll_path, L"._pth") && + exists(spbuffer)) + { return 1; } } if (config->program_full_path[0]) { - if (!change_ext(spbuffer, config->program_full_path, L"._pth") && exists(spbuffer)) { + if (!change_ext(spbuffer, config->program_full_path, L"._pth") && + exists(spbuffer)) + { return 1; } } @@ -823,8 +827,10 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (main_config->module_search_path_env!=NULL || calculate->home!=NULL || \ - calculate->machine_path!=NULL || calculate->user_path!=NULL); + int skipdefault = (main_config->module_search_path_env != NULL || + calculate->home != NULL || + calculate->machine_path != NULL || + calculate->user_path != NULL); /* We need to construct a path from the following parts. (1) the PYTHONPATH environment variable, if set; @@ -882,7 +888,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, start_buf = buf; if (main_config->module_search_path_env) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), main_config->module_search_path_env)) { + if (wcscpy_s(buf, bufsz - (buf - start_buf), + main_config->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -1214,7 +1221,7 @@ Py_GetProgramFullPath(void) static int python3_checked = 0; static HANDLE hPython3; int -_Py_CheckPython3() +_Py_CheckPython3(void) { wchar_t py3path[MAXPATHLEN+1]; wchar_t *s; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index f0a49f91fb8..a1b29f2a0eb 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1273,8 +1273,6 @@ Py_FinalizeEx(void) call_ll_exitfuncs(); - _PyPathConfig_Fini(); - _PyRuntime_Finalize(); return status; } From webhook-mailer at python.org Fri Dec 1 14:51:02 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 01 Dec 2017 19:51:02 -0000 Subject: [Python-checkins] bpo-32030: Add Python/pathconfig.c (#4668) Message-ID: https://github.com/python/cpython/commit/0ea395ae964c9cd0f499e2ef0d0030c971201220 commit: 0ea395ae964c9cd0f499e2ef0d0030c971201220 branch: master author: Victor Stinner committer: GitHub date: 2017-12-01T20:50:58+01:00 summary: bpo-32030: Add Python/pathconfig.c (#4668) * Factorize code from PC/getpathp.c and Modules/getpath.c to remove duplicated code * rename pathconfig_clear() to _PyPathConfig_Clear() * Inline _PyPathConfig_Fini() in pymain_impl() and then remove it, since it's a oneliner files: A Python/pathconfig.c M Include/internal/pystate.h M Include/pylifecycle.h M Makefile.pre.in M Modules/getpath.c M Modules/main.c M PC/getpathp.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/pylifecycle.c diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 50ad2fc83a3..9d8531965f1 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -52,6 +52,10 @@ typedef struct { #define _PyPathConfig_INIT {.module_search_path = NULL} +PyAPI_DATA(_PyPathConfig) _Py_path_config; + +PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); + /* Full Python runtime state */ diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 3db88326aee..fa751692a66 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -105,7 +105,6 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( const _PyMainInterpreterConfig *main_config); -PyAPI_FUNC(void) _PyPathConfig_Fini(void); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS diff --git a/Makefile.pre.in b/Makefile.pre.in index f425a89173a..14f6f8abc54 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -337,8 +337,9 @@ PYTHON_OBJS= \ Python/importdl.o \ Python/marshal.o \ Python/modsupport.o \ - Python/mystrtoul.o \ Python/mysnprintf.o \ + Python/mystrtoul.o \ + Python/pathconfig.o \ Python/peephole.o \ Python/pyarena.o \ Python/pyctype.o \ diff --git a/Modules/getpath.c b/Modules/getpath.c index 235badab230..8554dbe2a2c 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -132,7 +132,6 @@ typedef struct { static const wchar_t delimiter[2] = {DELIM, '\0'}; static const wchar_t separator[2] = {SEP, '\0'}; -static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; /* Get file status. Encode the path to the locale encoding. */ @@ -1009,23 +1008,6 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, } -static void -pathconfig_clear(_PyPathConfig *config) -{ -#define CLEAR(ATTR) \ - do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ - } while (0) - - CLEAR(config->prefix); - CLEAR(config->exec_prefix); - CLEAR(config->program_full_path); - CLEAR(config->module_search_path); -#undef CLEAR -} - - /* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() and Py_GetProgramFullPath() */ _PyInitError @@ -1049,7 +1031,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) err = calculate_path_impl(main_config, &calculate, &new_path_config); if (_Py_INIT_FAILED(err)) { - pathconfig_clear(&new_path_config); + _PyPathConfig_Clear(&new_path_config); goto done; } @@ -1061,100 +1043,6 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) return err; } - -static void -pathconfig_global_init(void) -{ - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return; - } - - _PyInitError err; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; - - err = _PyMainInterpreterConfig_ReadEnv(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - err = _PyMainInterpreterConfig_Read(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - err = _PyPathConfig_Init(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - _PyMainInterpreterConfig_Clear(&config); - return; - -error: - _PyMainInterpreterConfig_Clear(&config); - _Py_FatalInitError(err); -} - - -void -_PyPathConfig_Fini(void) -{ - pathconfig_clear(&_Py_path_config); -} - - -/* External interface */ -void -Py_SetPath(const wchar_t *path) -{ - if (path == NULL) { - pathconfig_clear(&_Py_path_config); - return; - } - - _PyPathConfig new_config; - new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); - new_config.exec_prefix = _PyMem_RawWcsdup(L""); - new_config.prefix = _PyMem_RawWcsdup(L""); - new_config.module_search_path = _PyMem_RawWcsdup(path); - - pathconfig_clear(&_Py_path_config); - _Py_path_config = new_config; -} - - -wchar_t * -Py_GetPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.module_search_path; -} - - -wchar_t * -Py_GetPrefix(void) -{ - pathconfig_global_init(); - return _Py_path_config.prefix; -} - - -wchar_t * -Py_GetExecPrefix(void) -{ - pathconfig_global_init(); - return _Py_path_config.exec_prefix; -} - - -wchar_t * -Py_GetProgramFullPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.program_full_path; -} - #ifdef __cplusplus } #endif diff --git a/Modules/main.c b/Modules/main.c index 4659c5d670b..6c1cf0d306a 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1665,12 +1665,12 @@ pymain_impl(_PyMain *pymain) pymain->status = 120; } - /* _PyPathConfig_Fini() cannot be called in Py_FinalizeEx(). + /* _PyPathConfig_Clear() cannot be called in Py_FinalizeEx(). Py_Initialize() and Py_Finalize() can be called multiple times, but it must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or - Py_SetPythonHome(), whereas _PyPathConfig_Fini() clear all these + Py_SetPythonHome(), whereas _PyPathConfig_Clear() clear all these parameters. */ - _PyPathConfig_Fini(); + _PyPathConfig_Clear(&_Py_path_config); return 0; } diff --git a/PC/getpathp.c b/PC/getpathp.c index f8cfd7e6978..3a0ebc10636 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -130,9 +130,6 @@ typedef struct { } PyCalculatePath; -static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; - - /* determine if "ch" is a separator character */ static int is_sep(wchar_t ch) @@ -1061,23 +1058,6 @@ calculate_free(PyCalculatePath *calculate) } -static void -pathconfig_clear(_PyPathConfig *config) -{ -#define CLEAR(ATTR) \ - do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ - } while (0) - - CLEAR(config->prefix); - CLEAR(config->program_full_path); - CLEAR(config->dll_path); - CLEAR(config->module_search_path); -#undef CLEAR -} - - /* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() and Py_GetProgramFullPath() */ _PyInitError @@ -1108,110 +1088,13 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) done: if (_Py_INIT_FAILED(err)) { - pathconfig_clear(&new_path_config); + _PyPathConfig_Clear(&new_path_config); } calculate_free(&calculate); return err; } -static void -pathconfig_global_init(void) -{ - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return; - } - - _PyInitError err; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; - - err = _PyMainInterpreterConfig_ReadEnv(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - err = _PyMainInterpreterConfig_Read(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - err = _PyPathConfig_Init(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - _PyMainInterpreterConfig_Clear(&config); - return; - -error: - _PyMainInterpreterConfig_Clear(&config); - _Py_FatalInitError(err); -} - - -void -_PyPathConfig_Fini(void) -{ - pathconfig_clear(&_Py_path_config); -} - - -/* External interface */ - -void -Py_SetPath(const wchar_t *path) -{ - if (_Py_path_config.module_search_path != NULL) { - pathconfig_clear(&_Py_path_config); - } - - if (path == NULL) { - return; - } - - _PyPathConfig new_config; - new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); - new_config.prefix = _PyMem_RawWcsdup(L""); - new_config.dll_path = _PyMem_RawWcsdup(L""); - new_config.module_search_path = _PyMem_RawWcsdup(path); - - pathconfig_clear(&_Py_path_config); - _Py_path_config = new_config; -} - - -wchar_t * -Py_GetPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.module_search_path; -} - - -wchar_t * -Py_GetPrefix(void) -{ - pathconfig_global_init(); - return _Py_path_config.prefix; -} - - -wchar_t * -Py_GetExecPrefix(void) -{ - return Py_GetPrefix(); -} - - -wchar_t * -Py_GetProgramFullPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.program_full_path; -} - - /* Load python3.dll before loading any extension module that might refer to it. That way, we can be sure that always the python3.dll corresponding to this python DLL is loaded, not a python3.dll that might be on the path diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 3793cbda882..b430e05b629 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -381,6 +381,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 1d33c6e2cc2..c9aa3da355e 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -896,6 +896,9 @@ Python + + Python + Python diff --git a/Python/pathconfig.c b/Python/pathconfig.c new file mode 100644 index 00000000000..daa22270369 --- /dev/null +++ b/Python/pathconfig.c @@ -0,0 +1,189 @@ +/* Path configuration like module_search_path (sys.path) */ + +#include "Python.h" +#include "osdefs.h" +#include "internal/pystate.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +_PyPathConfig _Py_path_config = _PyPathConfig_INIT; +#ifdef MS_WINDOWS +static wchar_t *progname = L"python"; +#else +static wchar_t *progname = L"python3"; +#endif +static wchar_t *default_home = NULL; + + +void +_PyPathConfig_Clear(_PyPathConfig *config) +{ +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->prefix); + CLEAR(config->program_full_path); +#ifdef MS_WINDOWS + CLEAR(config->dll_path); +#else + CLEAR(config->exec_prefix); +#endif + CLEAR(config->module_search_path); +#undef CLEAR +} + + +void +Py_SetProgramName(wchar_t *pn) +{ + if (pn && *pn) + progname = pn; +} + + +wchar_t * +Py_GetProgramName(void) +{ + return progname; +} + + +void +Py_SetPythonHome(wchar_t *home) +{ + default_home = home; +} + + +wchar_t* +Py_GetPythonHome(void) +{ + /* Use a static buffer to avoid heap memory allocation failure. + Py_GetPythonHome() doesn't allow to report error, and the caller + doesn't release memory. */ + static wchar_t buffer[MAXPATHLEN+1]; + + if (default_home) { + return default_home; + } + + char *home = Py_GETENV("PYTHONHOME"); + if (!home) { + return NULL; + } + + size_t size = Py_ARRAY_LENGTH(buffer); + size_t r = mbstowcs(buffer, home, size); + if (r == (size_t)-1 || r >= size) { + /* conversion failed or the static buffer is too small */ + return NULL; + } + + return buffer; +} + + +static void +pathconfig_global_init(void) +{ + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + + _PyInitError err; + _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + + err = _PyMainInterpreterConfig_ReadEnv(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + err = _PyMainInterpreterConfig_Read(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + err = _PyPathConfig_Init(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + _PyMainInterpreterConfig_Clear(&config); + return; + +error: + _PyMainInterpreterConfig_Clear(&config); + _Py_FatalInitError(err); +} + + +/* External interface */ + +void +Py_SetPath(const wchar_t *path) +{ + if (path == NULL) { + _PyPathConfig_Clear(&_Py_path_config); + return; + } + + _PyPathConfig new_config; + new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); + new_config.prefix = _PyMem_RawWcsdup(L""); +#ifdef MS_WINDOWS + new_config.dll_path = _PyMem_RawWcsdup(L""); +#else + new_config.exec_prefix = _PyMem_RawWcsdup(L""); +#endif + new_config.module_search_path = _PyMem_RawWcsdup(path); + + _PyPathConfig_Clear(&_Py_path_config); + _Py_path_config = new_config; +} + + +wchar_t * +Py_GetPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.module_search_path; +} + + +wchar_t * +Py_GetPrefix(void) +{ + pathconfig_global_init(); + return _Py_path_config.prefix; +} + + +wchar_t * +Py_GetExecPrefix(void) +{ +#ifdef MS_WINDOWS + return Py_GetPrefix(); +#else + pathconfig_global_init(); + return _Py_path_config.exec_prefix; +#endif +} + + +wchar_t * +Py_GetProgramFullPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.program_full_path; +} + +#ifdef __cplusplus +} +#endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index a1b29f2a0eb..8d71154c563 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1489,61 +1489,6 @@ Py_EndInterpreter(PyThreadState *tstate) PyInterpreterState_Delete(interp); } -#ifdef MS_WINDOWS -static wchar_t *progname = L"python"; -#else -static wchar_t *progname = L"python3"; -#endif - -void -Py_SetProgramName(wchar_t *pn) -{ - if (pn && *pn) - progname = pn; -} - -wchar_t * -Py_GetProgramName(void) -{ - return progname; -} - -static wchar_t *default_home = NULL; - -void -Py_SetPythonHome(wchar_t *home) -{ - default_home = home; -} - - -wchar_t* -Py_GetPythonHome(void) -{ - /* Use a static buffer to avoid heap memory allocation failure. - Py_GetPythonHome() doesn't allow to report error, and the caller - doesn't release memory. */ - static wchar_t buffer[MAXPATHLEN+1]; - - if (default_home) { - return default_home; - } - - char *home = Py_GETENV("PYTHONHOME"); - if (!home) { - return NULL; - } - - size_t size = Py_ARRAY_LENGTH(buffer); - size_t r = mbstowcs(buffer, home, size); - if (r == (size_t)-1 || r >= size) { - /* conversion failed or the static buffer is too small */ - return NULL; - } - - return buffer; -} - /* Add the __main__ module */ static _PyInitError From webhook-mailer at python.org Fri Dec 1 15:19:52 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 01 Dec 2017 20:19:52 -0000 Subject: [Python-checkins] bpo-32030: Fix config_get_program_name() on macOS (#4669) Message-ID: https://github.com/python/cpython/commit/e23c06e2b03452c9aaf0dae52296c85e572f9bcd commit: e23c06e2b03452c9aaf0dae52296c85e572f9bcd branch: master author: Victor Stinner committer: GitHub date: 2017-12-01T21:19:48+01:00 summary: bpo-32030: Fix config_get_program_name() on macOS (#4669) files: M Modules/main.c diff --git a/Modules/main.c b/Modules/main.c index 6c1cf0d306a..6c6c8018fd4 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -894,7 +894,7 @@ config_get_program_name(_PyMainInterpreterConfig *config) return SET_DECODE_ERROR("PYTHONEXECUTABLE environment " "variable", len); } - pymain->config.program_name = buffer; + config->program_name = program_name; } #ifdef WITH_NEXT_FRAMEWORK else { @@ -909,7 +909,7 @@ config_get_program_name(_PyMainInterpreterConfig *config) return SET_DECODE_ERROR("__PYVENV_LAUNCHER__ environment " "variable", len); } - pymain->config.program_name = program_name; + config->program_name = program_name; } } #endif /* WITH_NEXT_FRAMEWORK */ From lp_benchmark_robot at intel.com Fri Dec 1 17:59:14 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 1 Dec 2017 14:59:14 -0800 Subject: [Python-checkins] [1 up, 64 flat] Results for Python (master branch) 2017-12-01 Message-ID: Results for project python/master, build date: 2017-12-01 03:02:57-08:00. - commit: bf2b65e - previous commit: 5e3806f - revision date: 2017-12-01 08:08:49+01:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.891% | +0.581% | +5.653% | +6.981% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.915% | +1.892% | +22.959% | +5.594% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.994% | +1.916% | +23.455% | +5.097% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.604% | +1.094% | +21.572% | +5.007% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.368% | +3.957% | +9.200% | +7.669% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.709% | +1.565% | +9.744% | +12.317% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.708% | +1.045% | +7.037% | +9.537% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.471% | -0.367% | +0.651% | +8.398% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.695% | -0.099% | +5.943% | +19.532% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.685% | -3.256% | +11.837% | +4.974% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.065% | -0.927% | +4.326% | +6.839% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.373% | -0.152% | +5.622% | +5.118% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.757% | +1.209% | +3.193% | +5.480% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 0.907% | +0.636% | +14.252% | +8.386% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 2.254% | +0.554% | +9.232% | +9.210% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.893% | +0.241% | +5.930% | +10.218% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.380% | -0.029% | +10.810% | +11.159% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.927% | -0.536% | +9.017% | +7.717% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 0.989% | +0.447% | +3.310% | +9.878% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 1.797% | +1.125% | +0.639% | +12.282% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.693% | -1.284% | +6.265% | +13.124% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.692% | -0.748% | +47.186% | +10.589% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.767% | +0.115% | +7.573% | +12.896% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.386% | +0.303% | +17.260% | +12.289% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.975% | -0.129% | +7.520% | +11.324% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.376% | +0.136% | +3.353% | +6.336% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.416% | -0.359% | +0.230% | -1.284% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.777% | +0.935% | +4.760% | +7.175% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.713% | +0.578% | +5.661% | +10.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.146% | -0.962% | +0.866% | +20.690% | +-----+------------------------+--------+------------+------------+------------+ | :-) | pickle_dict| 1.041% | +4.205% | +1.345% | +22.494% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.776% | +1.027% | +2.598% | +19.845% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 2.571% | -0.089% | +11.996% | +9.240% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.069% | +0.062% | +0.159% | +10.235% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.137% | -0.287% | +10.559% | +5.074% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.107% | -0.220% | +1.925% | +5.277% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.061% | -0.281% | +9.840% | +12.953% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.492% | -0.453% | +0.675% | +11.474% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.324% | -0.004% | -1.327% | +10.285% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.698% | +3.638% | -2.773% | +7.394% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.412% | +0.318% | +5.291% | +6.450% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.608% | +0.462% | +8.205% | +13.309% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.745% | -0.311% | -1.979% | +5.249% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.185% | +0.565% | +28.236% | +7.653% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.630% | +0.290% | +5.294% | +4.261% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.039% | +0.421% | +14.024% | +8.597% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.555% | -1.063% | -2.170% | +3.558% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.657% | -0.421% | +4.125% | +4.148% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.145% | -0.304% | +6.299% | +7.017% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.422% | -0.379% | +6.337% | +3.245% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.592% | +0.931% | +18.148% | +8.487% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.645% | -0.438% | +11.496% | +7.368% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.035% | -0.253% | +9.021% | +6.761% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.153% | -0.391% | +11.137% | +8.440% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 4.756% | +0.716% | +11.553% | +7.477% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 2.836% | +2.358% | +23.799% | +7.958% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.221% | -0.631% | +5.356% | +6.712% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.844% | +0.192% | +2.283% | +2.423% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 5.501% | -1.049% | +8.532% | +19.352% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.394% | -3.145% | -3.027% | +18.572% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 0.625% | +1.006% | +6.962% | +7.869% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.994% | -0.158% | +5.943% | +8.328% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.363% | -0.470% | +3.128% | +9.055% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.055% | -0.316% | -7.390% | +13.744% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.257% | +0.035% | +7.128% | +9.051% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-up-64-flat-results-for-python-master-branch-2017-12-01 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From solipsis at pitrou.net Sat Dec 2 04:10:51 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 02 Dec 2017 09:10:51 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171202091051.10296.BC30A801E492D64D@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogNV_0_n', '--timeout', '7200'] From webhook-mailer at python.org Sat Dec 2 04:11:39 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Sat, 02 Dec 2017 09:11:39 -0000 Subject: [Python-checkins] bpo-32030: _PyPathConfig_Init() sets home and program_name (#4673) Message-ID: https://github.com/python/cpython/commit/af5a895073c24637c094772b27526b94a12ec897 commit: af5a895073c24637c094772b27526b94a12ec897 branch: master author: Victor Stinner committer: GitHub date: 2017-12-02T10:11:32+01:00 summary: bpo-32030: _PyPathConfig_Init() sets home and program_name (#4673) _PyPathConfig_Init() now also initialize home and program_name: * Rename existing _PyPathConfig_Init() to _PyPathConfig_Calculate(). Add a new _PyPathConfig_Init() function in pathconfig.c which handles the _Py_path_config variable and call _PyPathConfig_Calculate(). * Add home and program_name fields to _PyPathConfig.home * _PyPathConfig_Init() now initialize home and program_name from main_config * Py_SetProgramName(), Py_SetPythonHome() and Py_GetPythonHome() now calls Py_FatalError() on failure, instead of silently ignoring failures. * config_init_home() now gets directly _Py_path_config.home to only get the value set by Py_SetPythonHome(), or NULL if Py_SetPythonHome() was not called. * config_get_program_name() now gets directly _Py_path_config.program_name to only get the value set by Py_SetProgramName(), or NULL if Py_SetProgramName() was not called. * pymain_init_python() doesn't call Py_SetProgramName() anymore, _PyPathConfig_Init() now always sets the program name * Call _PyMainInterpreterConfig_Read() in pymain_parse_cmdline_envvars_impl() to control the memory allocator * C API documentation: it's no more safe to call Py_GetProgramName() before Py_Initialize(). files: M Doc/c-api/init.rst M Include/internal/pystate.h M Include/pystate.h M Modules/getpath.c M Modules/main.c M PC/getpathp.c M Python/pathconfig.c M Python/pylifecycle.c diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index a9927aba5e1..a3113a390fd 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -40,7 +40,6 @@ The following functions can be safely called before Python is initialized: * :c:func:`Py_GetCompiler` * :c:func:`Py_GetCopyright` * :c:func:`Py_GetPlatform` - * :c:func:`Py_GetProgramName` * :c:func:`Py_GetVersion` * Utilities: @@ -59,8 +58,8 @@ The following functions can be safely called before Python is initialized: The following functions **should not be called** before :c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`, :c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`, - :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome` and - :c:func:`PyEval_InitThreads`. + :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`, + :c:func:`Py_GetProgramName` and :c:func:`PyEval_InitThreads`. .. _global-conf-vars: diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 9d8531965f1..b9334212047 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -48,12 +48,35 @@ typedef struct { #endif /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */ wchar_t *module_search_path; + /* Python program name */ + wchar_t *program_name; + /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */ + wchar_t *home; } _PyPathConfig; -#define _PyPathConfig_INIT {.module_search_path = NULL} +#ifdef MS_WINDOWS +#define _PyPathConfig_INIT \ + {.program_full_path = NULL, \ + .prefix = NULL, \ + .dll_path = NULL, \ + .module_search_path = NULL, \ + .program_name = NULL, \ + .home = NULL} +#else +#define _PyPathConfig_INIT \ + {.program_full_path = NULL, \ + .prefix = NULL, \ + .exec_prefix = NULL, \ + .module_search_path = NULL, \ + .program_name = NULL, \ + .home = NULL} +#endif PyAPI_DATA(_PyPathConfig) _Py_path_config; +PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate( + _PyPathConfig *config, + const _PyMainInterpreterConfig *main_config); PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); diff --git a/Include/pystate.h b/Include/pystate.h index 60d001c4926..1d8aab6d83f 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -72,7 +72,8 @@ typedef struct { (_PyMainInterpreterConfig){\ .install_signal_handlers = -1, \ .module_search_path_env = NULL, \ - .home = NULL} + .home = NULL, \ + .program_name = NULL} typedef struct _is { diff --git a/Modules/getpath.c b/Modules/getpath.c index 8554dbe2a2c..fc2b5442ce2 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -1008,16 +1008,10 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, } -/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() - and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, + const _PyMainInterpreterConfig *main_config) { - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return _Py_INIT_OK(); - } - PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); @@ -1026,16 +1020,11 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - _PyPathConfig new_path_config; - memset(&new_path_config, 0, sizeof(new_path_config)); - - err = calculate_path_impl(main_config, &calculate, &new_path_config); + err = calculate_path_impl(main_config, &calculate, config); if (_Py_INIT_FAILED(err)) { - _PyPathConfig_Clear(&new_path_config); goto done; } - _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: diff --git a/Modules/main.c b/Modules/main.c index 6c6c8018fd4..84706e1e290 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -876,6 +876,16 @@ static _PyInitError config_get_program_name(_PyMainInterpreterConfig *config) { assert(config->program_name == NULL); + + /* If Py_SetProgramName() was called, use its value */ + wchar_t *program_name = _Py_path_config.program_name; + if (program_name != NULL) { + config->program_name = _PyMem_RawWcsdup(program_name); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + #ifdef __APPLE__ char *p; /* On MacOS X, when the Python interpreter is embedded in an @@ -914,6 +924,7 @@ config_get_program_name(_PyMainInterpreterConfig *config) } #endif /* WITH_NEXT_FRAMEWORK */ #endif /* __APPLE__ */ + return _Py_INIT_OK(); } @@ -948,13 +959,6 @@ pymain_init_main_interpreter(_PyMain *pymain) { _PyInitError err; - /* TODO: Print any exceptions raised by these operations */ - err = _PyMainInterpreterConfig_Read(&pymain->config); - if (_Py_INIT_FAILED(err)) { - pymain->err = err; - return -1; - } - err = _Py_InitializeMainInterpreter(&pymain->config); if (_Py_INIT_FAILED(err)) { pymain->err = err; @@ -1412,14 +1416,13 @@ config_init_pythonpath(_PyMainInterpreterConfig *config) static _PyInitError -config_init_pythonhome(_PyMainInterpreterConfig *config) +config_init_home(_PyMainInterpreterConfig *config) { wchar_t *home; - home = Py_GetPythonHome(); + /* If Py_SetPythonHome() was called, use its value */ + home = _Py_path_config.home; if (home) { - /* Py_SetPythonHome() has been called before Py_Main(), - use its value */ config->home = _PyMem_RawWcsdup(home); if (config->home == NULL) { return _Py_INIT_NO_MEMORY(); @@ -1439,7 +1442,7 @@ config_init_pythonhome(_PyMainInterpreterConfig *config) _PyInitError _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) { - _PyInitError err = config_init_pythonhome(config); + _PyInitError err = config_init_home(config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1543,6 +1546,12 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) return -1; } + _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; + return -1; + } + return 0; } @@ -1566,11 +1575,6 @@ pymain_init_python(_PyMain *pymain) { pymain_init_stdio(pymain); - Py_SetProgramName(pymain->config.program_name); - /* Don't free program_name here: the argument to Py_SetProgramName - must remain valid until Py_FinalizeEx is called. The string is freed - by pymain_free(). */ - pymain->err = _Py_InitializeCore(&pymain->core_config); if (_Py_INIT_FAILED(pymain->err)) { return -1; diff --git a/PC/getpathp.c b/PC/getpathp.c index 3a0ebc10636..08ed8ccc83f 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -1058,38 +1058,23 @@ calculate_free(PyCalculatePath *calculate) } -/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() - and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, + const _PyMainInterpreterConfig *main_config) { - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return _Py_INIT_OK(); - } - - _PyInitError err; - PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); calculate_init(&calculate, main_config); - _PyPathConfig new_path_config; - memset(&new_path_config, 0, sizeof(new_path_config)); - - err = calculate_path_impl(main_config, &calculate, &new_path_config); + _PyInitError err = calculate_path_impl(main_config, &calculate, config); if (_Py_INIT_FAILED(err)) { goto done; } - _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: - if (_Py_INIT_FAILED(err)) { - _PyPathConfig_Clear(&new_path_config); - } calculate_free(&calculate); return err; } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index daa22270369..6a03f7dca1b 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -10,17 +10,17 @@ extern "C" { _PyPathConfig _Py_path_config = _PyPathConfig_INIT; -#ifdef MS_WINDOWS -static wchar_t *progname = L"python"; -#else -static wchar_t *progname = L"python3"; -#endif -static wchar_t *default_home = NULL; void _PyPathConfig_Clear(_PyPathConfig *config) { + /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator, + since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be + called before Py_Initialize() which can changes the memory allocator. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + #define CLEAR(ATTR) \ do { \ PyMem_RawFree(ATTR); \ @@ -35,57 +35,64 @@ _PyPathConfig_Clear(_PyPathConfig *config) CLEAR(config->exec_prefix); #endif CLEAR(config->module_search_path); + CLEAR(config->home); + CLEAR(config->program_name); #undef CLEAR -} - -void -Py_SetProgramName(wchar_t *pn) -{ - if (pn && *pn) - progname = pn; + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } -wchar_t * -Py_GetProgramName(void) +/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() + and Py_GetProgramFullPath() */ +_PyInitError +_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) { - return progname; -} - - -void -Py_SetPythonHome(wchar_t *home) -{ - default_home = home; -} + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return _Py_INIT_OK(); + } + _PyInitError err; + _PyPathConfig new_config = _PyPathConfig_INIT; -wchar_t* -Py_GetPythonHome(void) -{ - /* Use a static buffer to avoid heap memory allocation failure. - Py_GetPythonHome() doesn't allow to report error, and the caller - doesn't release memory. */ - static wchar_t buffer[MAXPATHLEN+1]; + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - if (default_home) { - return default_home; + /* Calculate program_full_path, prefix, exec_prefix (Unix) + or dll_path (Windows), and module_search_path */ + err = _PyPathConfig_Calculate(&new_config, main_config); + if (_Py_INIT_FAILED(err)) { + _PyPathConfig_Clear(&new_config); + goto done; } - char *home = Py_GETENV("PYTHONHOME"); - if (!home) { - return NULL; + /* Copy home and program_name from main_config */ + if (main_config->home != NULL) { + new_config.home = _PyMem_RawWcsdup(main_config->home); + if (new_config.home == NULL) { + err = _Py_INIT_NO_MEMORY(); + goto done; + } + } + else { + new_config.home = NULL; } - size_t size = Py_ARRAY_LENGTH(buffer); - size_t r = mbstowcs(buffer, home, size); - if (r == (size_t)-1 || r >= size) { - /* conversion failed or the static buffer is too small */ - return NULL; + new_config.program_name = _PyMem_RawWcsdup(main_config->program_name); + if (new_config.program_name == NULL) { + err = _Py_INIT_NO_MEMORY(); + goto done; } - return buffer; + _PyPathConfig_Clear(&_Py_path_config); + _Py_path_config = new_config; + + err = _Py_INIT_OK(); + +done: + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + return err; } @@ -134,6 +141,9 @@ Py_SetPath(const wchar_t *path) return; } + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + _PyPathConfig new_config; new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); new_config.prefix = _PyMem_RawWcsdup(L""); @@ -144,8 +154,58 @@ Py_SetPath(const wchar_t *path) #endif new_config.module_search_path = _PyMem_RawWcsdup(path); + /* steal the home and program_name values (to leave them unchanged) */ + new_config.home = _Py_path_config.home; + _Py_path_config.home = NULL; + new_config.program_name = _Py_path_config.program_name; + _Py_path_config.program_name = NULL; + _PyPathConfig_Clear(&_Py_path_config); _Py_path_config = new_config; + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + + +void +Py_SetPythonHome(wchar_t *home) +{ + if (home == NULL) { + return; + } + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + PyMem_RawFree(_Py_path_config.home); + _Py_path_config.home = _PyMem_RawWcsdup(home); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + if (_Py_path_config.home == NULL) { + Py_FatalError("Py_SetPythonHome() failed: out of memory"); + } +} + + +void +Py_SetProgramName(wchar_t *program_name) +{ + if (program_name == NULL || program_name[0] == L'\0') { + return; + } + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + PyMem_RawFree(_Py_path_config.program_name); + _Py_path_config.program_name = _PyMem_RawWcsdup(program_name); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + if (_Py_path_config.program_name == NULL) { + Py_FatalError("Py_SetProgramName() failed: out of memory"); + } } @@ -184,6 +244,23 @@ Py_GetProgramFullPath(void) return _Py_path_config.program_full_path; } + +wchar_t* +Py_GetPythonHome(void) +{ + pathconfig_global_init(); + return _Py_path_config.home; +} + + +wchar_t * +Py_GetProgramName(void) +{ + pathconfig_global_init(); + return _Py_path_config.program_name; +} + + #ifdef __cplusplus } #endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 8d71154c563..523397f1269 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -804,7 +804,12 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) } if (config->program_name == NULL) { - config->program_name = _PyMem_RawWcsdup(Py_GetProgramName()); +#ifdef MS_WINDOWS + const wchar_t *program_name = L"python"; +#else + const wchar_t *program_name = L"python3"; +#endif + config->program_name = _PyMem_RawWcsdup(program_name); if (config->program_name == NULL) { return _Py_INIT_NO_MEMORY(); } From webhook-mailer at python.org Sat Dec 2 14:00:12 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 02 Dec 2017 19:00:12 -0000 Subject: [Python-checkins] [2.7] bpo-10544: Deprecate "yield" in comprehensions and generator expressions in Py3k mode. (GH-4579) (#4676) Message-ID: https://github.com/python/cpython/commit/65d1887170fb278c10a836e9e4319cae4707f524 commit: 65d1887170fb278c10a836e9e4319cae4707f524 branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2017-12-02T21:00:09+02:00 summary: [2.7] bpo-10544: Deprecate "yield" in comprehensions and generator expressions in Py3k mode. (GH-4579) (#4676) files: A Misc/NEWS.d/next/Core and Builtins/2017-11-27-08-37-34.bpo-10544.07nioT.rst M Lib/test/support/__init__.py M Lib/test/test_generators.py M Lib/test/test_grammar.py M Python/symtable.c diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 0f0da72b190..cabf548ec38 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -847,8 +847,8 @@ def make_bad_fd(): file.close() unlink(TESTFN) -def check_syntax_error(testcase, statement, lineno=None, offset=None): - with testcase.assertRaises(SyntaxError) as cm: +def check_syntax_error(testcase, statement, errtext='', lineno=None, offset=None): + with testcase.assertRaisesRegexp(SyntaxError, errtext) as cm: compile(statement, '', 'exec') err = cm.exception if lineno is not None: diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 5e1a3e52d50..0f7bf19abb8 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1524,13 +1524,7 @@ def printsolution(self, x): [None] - -An obscene abuse of a yield expression within a generator expression: - ->>> list((yield 21) for i in range(4)) -[21, None, 21, None, 21, None, 21, None] - -And a more sane, but still weird usage: +Yield is allowed only in the outermost iterable in generator expression: >>> def f(): list(i for i in [(yield 26)]) >>> type(f()) @@ -1571,7 +1565,7 @@ def printsolution(self, x): >>> def f(): return lambda x=(yield): 1 Traceback (most recent call last): ... -SyntaxError: 'return' with argument inside generator (, line 1) +SyntaxError: 'return' with argument inside generator (, line 1) >>> def f(): x = yield = y Traceback (most recent call last): @@ -1784,7 +1778,7 @@ def printsolution(self, x): >>> type(f()) ->>> def f(): x=(i for i in (yield) if (yield)) +>>> def f(): x=(i for i in (yield) if i) >>> type(f()) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 5f77c1d018b..fc675c35a30 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -493,6 +493,46 @@ def g2(): return 1 def testYield(self): check_syntax_error(self, "class foo:yield 1") + def test_yield_in_comprehensions(self): + # Check yield in comprehensions + def g(): [x for x in [(yield 1)]] + + def check(code, warntext): + with check_py3k_warnings((warntext, DeprecationWarning)): + compile(code, '', 'exec') + if sys.py3kwarning: + import warnings + with warnings.catch_warnings(): + warnings.filterwarnings('error', category=DeprecationWarning) + with self.assertRaises(SyntaxError) as cm: + compile(code, '', 'exec') + self.assertIn(warntext, str(cm.exception)) + + check("def g(): [(yield x) for x in ()]", + "'yield' inside list comprehension") + check("def g(): [x for x in () if not (yield x)]", + "'yield' inside list comprehension") + check("def g(): [y for x in () for y in [(yield x)]]", + "'yield' inside list comprehension") + check("def g(): {(yield x) for x in ()}", + "'yield' inside set comprehension") + check("def g(): {(yield x): x for x in ()}", + "'yield' inside dict comprehension") + check("def g(): {x: (yield x) for x in ()}", + "'yield' inside dict comprehension") + check("def g(): ((yield x) for x in ())", + "'yield' inside generator expression") + with check_py3k_warnings(("'yield' inside list comprehension", + DeprecationWarning)): + check_syntax_error(self, "class C: [(yield x) for x in ()]") + check("class C: ((yield x) for x in ())", + "'yield' inside generator expression") + with check_py3k_warnings(("'yield' inside list comprehension", + DeprecationWarning)): + check_syntax_error(self, "[(yield x) for x in ()]") + check("((yield x) for x in ())", + "'yield' inside generator expression") + def testRaise(self): # 'raise' test [',' test] try: raise RuntimeError, 'just testing' diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-11-27-08-37-34.bpo-10544.07nioT.rst b/Misc/NEWS.d/next/Core and Builtins/2017-11-27-08-37-34.bpo-10544.07nioT.rst new file mode 100644 index 00000000000..d0d3a75c4cd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-11-27-08-37-34.bpo-10544.07nioT.rst @@ -0,0 +1,4 @@ +Yield expressions are now deprecated in comprehensions and generator +expressions when checking Python 3 compatibility. They are still +permitted in the definition of the outermost iterable, as that is +evaluated directly in the enclosing scope. diff --git a/Python/symtable.c b/Python/symtable.c index 3b4247b4153..21790b1cd18 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -162,12 +162,14 @@ PyTypeObject PySTEntry_Type = { }; static int symtable_analyze(struct symtable *st); -static int symtable_warn(struct symtable *st, char *msg, int lineno); +static int symtable_warn(struct symtable *st, + PyObject *warn, const char *msg, int lineno); static int symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, void *ast, int lineno); static int symtable_exit_block(struct symtable *st, void *ast); static int symtable_visit_stmt(struct symtable *st, stmt_ty s); static int symtable_visit_expr(struct symtable *st, expr_ty s); +static int symtable_visit_listcomp(struct symtable *st, expr_ty e); static int symtable_visit_genexp(struct symtable *st, expr_ty s); static int symtable_visit_setcomp(struct symtable *st, expr_ty e); static int symtable_visit_dictcomp(struct symtable *st, expr_ty e); @@ -796,14 +798,18 @@ symtable_analyze(struct symtable *st) static int -symtable_warn(struct symtable *st, char *msg, int lineno) +symtable_warn(struct symtable *st, PyObject *warn, const char *msg, int lineno) { - if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename, - lineno, NULL, NULL) < 0) { - if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { + if (lineno < 0) { + lineno = st->st_cur->ste_lineno; + } + if (PyErr_WarnExplicit(warn, msg, st->st_filename, lineno, NULL, NULL) < 0) { + if (PyErr_ExceptionMatches(warn)) { + /* Replace the warning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); PyErr_SetString(PyExc_SyntaxError, msg); - PyErr_SyntaxLocation(st->st_filename, - st->st_cur->ste_lineno); + PyErr_SyntaxLocation(st->st_filename, lineno); } return 0; } @@ -1153,7 +1159,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) PyOS_snprintf(buf, sizeof(buf), GLOBAL_AFTER_USE, c_name); - if (!symtable_warn(st, buf, s->lineno)) + if (!symtable_warn(st, PyExc_SyntaxWarning, buf, s->lineno)) return 0; } if (!symtable_add_def(st, name, DEF_GLOBAL)) @@ -1221,8 +1227,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT_SEQ(st, expr, e->v.Set.elts); break; case ListComp_kind: - VISIT(st, expr, e->v.ListComp.elt); - VISIT_SEQ(st, comprehension, e->v.ListComp.generators); + if (!symtable_visit_listcomp(st, e)) + return 0; break; case GeneratorExp_kind: if (!symtable_visit_genexp(st, e)) @@ -1420,12 +1426,11 @@ symtable_visit_alias(struct symtable *st, alias_ty a) return r; } else { - if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - if (!symtable_warn(st, IMPORT_STAR_WARNING, lineno)) { - Py_DECREF(store_name); - return 0; - } + if (st->st_cur->ste_type != ModuleBlock && + !symtable_warn(st, PyExc_SyntaxWarning, IMPORT_STAR_WARNING, -1)) + { + Py_DECREF(store_name); + return 0; } st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; Py_DECREF(store_name); @@ -1509,7 +1514,10 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, 0)) { return 0; } - st->st_cur->ste_generator = is_generator; + /* In order to check for yield expressions under '-3', we clear + the generator flag, and restore it at the end */ + is_generator |= st->st_cur->ste_generator; + st->st_cur->ste_generator = 0; /* Outermost iter is received as an argument */ if (!symtable_implicit_arg(st, 0)) { symtable_exit_block(st, (void *)e); @@ -1527,9 +1535,55 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, if (value) VISIT_IN_BLOCK(st, expr, value, (void*)e); VISIT_IN_BLOCK(st, expr, elt, (void*)e); + if (Py_Py3kWarningFlag && st->st_cur->ste_generator) { + const char *msg = ( + (e->kind == SetComp_kind) ? "'yield' inside set comprehension" : + (e->kind == DictComp_kind) ? "'yield' inside dict comprehension" : + "'yield' inside generator expression"); + if (!symtable_warn(st, PyExc_DeprecationWarning, msg, -1)) { + symtable_exit_block(st, (void *)e); + return 0; + } + } + st->st_cur->ste_generator |= is_generator; return symtable_exit_block(st, (void *)e); } +static int +symtable_visit_listcomp(struct symtable *st, expr_ty e) +{ + asdl_seq *generators = e->v.ListComp.generators; + int i, is_generator; + /* In order to check for yield expressions under '-3', we clear + the generator flag, and restore it at the end */ + is_generator = st->st_cur->ste_generator; + st->st_cur->ste_generator = 0; + VISIT(st, expr, e->v.ListComp.elt); + for (i = 0; i < asdl_seq_LEN(generators); i++) { + comprehension_ty lc = (comprehension_ty)asdl_seq_GET(generators, i); + VISIT(st, expr, lc->target); + if (i == 0 && !st->st_cur->ste_generator) { + /* 'yield' in the outermost iterator doesn't cause a warning */ + VISIT(st, expr, lc->iter); + is_generator |= st->st_cur->ste_generator; + st->st_cur->ste_generator = 0; + } + else { + VISIT(st, expr, lc->iter); + } + VISIT_SEQ(st, expr, lc->ifs); + } + + if (Py_Py3kWarningFlag && st->st_cur->ste_generator) { + const char *msg = "'yield' inside list comprehension"; + if (!symtable_warn(st, PyExc_DeprecationWarning, msg, -1)) { + return 0; + } + } + st->st_cur->ste_generator |= is_generator; + return 1; +} + static int symtable_visit_genexp(struct symtable *st, expr_ty e) { From webhook-mailer at python.org Sat Dec 2 14:36:03 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 02 Dec 2017 19:36:03 -0000 Subject: [Python-checkins] bpo-32197: Try to fix a compiler error on OS X introduced in bpo-32030. (#4681) Message-ID: https://github.com/python/cpython/commit/13badcbc60cdbfae1dba1683fd2fae9d70717143 commit: 13badcbc60cdbfae1dba1683fd2fae9d70717143 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-02T21:36:00+02:00 summary: bpo-32197: Try to fix a compiler error on OS X introduced in bpo-32030. (#4681) * Revert "bpo-32030: _PyPathConfig_Init() sets home and program_name (#4673)" This reverts commit af5a895073c24637c094772b27526b94a12ec897. * Revert "bpo-32030: Fix config_get_program_name() on macOS (#4669)" This reverts commit e23c06e2b03452c9aaf0dae52296c85e572f9bcd. * Revert "bpo-32030: Add Python/pathconfig.c (#4668)" This reverts commit 0ea395ae964c9cd0f499e2ef0d0030c971201220. * Revert "bpo-32030: Don't call _PyPathConfig_Fini() in Py_FinalizeEx() (#4667)" This reverts commit ebac19dad6263141d5db0a2c923efe049dba99d2. * Revert "bpo-32030: Fix Py_GetPath(): init program_name (#4665)" This reverts commit 9ac3d8882712c9675c3d2f9f84af6b5729575cde. files: D Python/pathconfig.c M Doc/c-api/init.rst M Include/internal/pystate.h M Include/pylifecycle.h M Include/pystate.h M Makefile.pre.in M Modules/getpath.c M Modules/main.c M PC/getpathp.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/pylifecycle.c diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index a3113a390fd..a9927aba5e1 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -40,6 +40,7 @@ The following functions can be safely called before Python is initialized: * :c:func:`Py_GetCompiler` * :c:func:`Py_GetCopyright` * :c:func:`Py_GetPlatform` + * :c:func:`Py_GetProgramName` * :c:func:`Py_GetVersion` * Utilities: @@ -58,8 +59,8 @@ The following functions can be safely called before Python is initialized: The following functions **should not be called** before :c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`, :c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`, - :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`, - :c:func:`Py_GetProgramName` and :c:func:`PyEval_InitThreads`. + :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome` and + :c:func:`PyEval_InitThreads`. .. _global-conf-vars: diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index b9334212047..50ad2fc83a3 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -48,36 +48,9 @@ typedef struct { #endif /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */ wchar_t *module_search_path; - /* Python program name */ - wchar_t *program_name; - /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */ - wchar_t *home; } _PyPathConfig; -#ifdef MS_WINDOWS -#define _PyPathConfig_INIT \ - {.program_full_path = NULL, \ - .prefix = NULL, \ - .dll_path = NULL, \ - .module_search_path = NULL, \ - .program_name = NULL, \ - .home = NULL} -#else -#define _PyPathConfig_INIT \ - {.program_full_path = NULL, \ - .prefix = NULL, \ - .exec_prefix = NULL, \ - .module_search_path = NULL, \ - .program_name = NULL, \ - .home = NULL} -#endif - -PyAPI_DATA(_PyPathConfig) _Py_path_config; - -PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate( - _PyPathConfig *config, - const _PyMainInterpreterConfig *main_config); -PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); +#define _PyPathConfig_INIT {.module_search_path = NULL} /* Full Python runtime state */ diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index fa751692a66..d32c98b6985 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -105,10 +105,11 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( const _PyMainInterpreterConfig *main_config); +PyAPI_FUNC(void) _PyPathConfig_Fini(void); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS -int _Py_CheckPython3(void); +int _Py_CheckPython3(); #endif /* In their own files */ diff --git a/Include/pystate.h b/Include/pystate.h index 1d8aab6d83f..60d001c4926 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -72,8 +72,7 @@ typedef struct { (_PyMainInterpreterConfig){\ .install_signal_handlers = -1, \ .module_search_path_env = NULL, \ - .home = NULL, \ - .program_name = NULL} + .home = NULL} typedef struct _is { diff --git a/Makefile.pre.in b/Makefile.pre.in index 14f6f8abc54..f425a89173a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -337,9 +337,8 @@ PYTHON_OBJS= \ Python/importdl.o \ Python/marshal.o \ Python/modsupport.o \ - Python/mysnprintf.o \ Python/mystrtoul.o \ - Python/pathconfig.o \ + Python/mysnprintf.o \ Python/peephole.o \ Python/pyarena.o \ Python/pyctype.o \ diff --git a/Modules/getpath.c b/Modules/getpath.c index fc2b5442ce2..9f5e8b3ff5c 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -117,7 +117,10 @@ extern "C" { typedef struct { wchar_t *path_env; /* PATH environment variable */ + wchar_t *home; /* PYTHONHOME environment variable */ + wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ + wchar_t *program_name; /* Program name */ wchar_t *pythonpath; /* PYTHONPATH define */ wchar_t *prefix; /* PREFIX define */ wchar_t *exec_prefix; /* EXEC_PREFIX define */ @@ -132,6 +135,7 @@ typedef struct { static const wchar_t delimiter[2] = {DELIM, '\0'}; static const wchar_t separator[2] = {SEP, '\0'}; +static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; /* Get file status. Encode the path to the locale encoding. */ @@ -356,15 +360,14 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) bytes long. */ static int -search_for_prefix(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, wchar_t *prefix) +search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix) { size_t n; wchar_t *vpath; /* If PYTHONHOME is set, we believe it unconditionally */ - if (main_config->home) { - wcsncpy(prefix, main_config->home, MAXPATHLEN); + if (calculate->home) { + wcsncpy(prefix, calculate->home, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; wchar_t *delim = wcschr(prefix, DELIM); if (delim) { @@ -423,10 +426,9 @@ search_for_prefix(const _PyMainInterpreterConfig *main_config, static void -calculate_prefix(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, wchar_t *prefix) +calculate_prefix(PyCalculatePath *calculate, wchar_t *prefix) { - calculate->prefix_found = search_for_prefix(main_config, calculate, prefix); + calculate->prefix_found = search_for_prefix(calculate, prefix); if (!calculate->prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -468,19 +470,18 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) MAXPATHLEN bytes long. */ static int -search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, wchar_t *exec_prefix) +search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) { size_t n; /* If PYTHONHOME is set, we believe it unconditionally */ - if (main_config->home) { - wchar_t *delim = wcschr(main_config->home, DELIM); + if (calculate->home) { + wchar_t *delim = wcschr(calculate->home, DELIM); if (delim) { wcsncpy(exec_prefix, delim+1, MAXPATHLEN); } else { - wcsncpy(exec_prefix, main_config->home, MAXPATHLEN); + wcsncpy(exec_prefix, calculate->home, MAXPATHLEN); } exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, calculate->lib_python); @@ -551,12 +552,9 @@ search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, static void -calculate_exec_prefix(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, wchar_t *exec_prefix) +calculate_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) { - calculate->exec_prefix_found = search_for_exec_prefix(main_config, - calculate, - exec_prefix); + calculate->exec_prefix_found = search_for_exec_prefix(calculate, exec_prefix); if (!calculate->exec_prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -587,8 +585,7 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static _PyInitError -calculate_program_full_path(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, _PyPathConfig *config) +calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); @@ -607,8 +604,8 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, * other way to find a directory to start the search from. If * $PATH isn't exported, you lose. */ - if (wcschr(main_config->program_name, SEP)) { - wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); + if (wcschr(calculate->program_name, SEP)) { + wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -624,13 +621,11 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { - size_t len; - wchar_t *path = Py_DecodeLocale(execpath, &len); - if (path == NULL) { - return DECODE_LOCALE_ERR("executable path", len); + size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1); + if (r == (size_t)-1 || r > MAXPATHLEN) { + /* Could not convert execpath, or it's too long. */ + program_full_path[0] = '\0'; } - wcsncpy(program_full_path, path, MAXPATHLEN); - PyMem_RawFree(path); } #endif /* __APPLE__ */ else if (calculate->path_env) { @@ -650,7 +645,7 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_full_path, main_config->program_name); + joinpath(program_full_path, calculate->program_name); if (isxfile(program_full_path)) { break; } @@ -815,15 +810,14 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) static _PyInitError -calculate_module_search_path(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, +calculate_module_search_path(PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, _PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; - if (main_config->module_search_path_env != NULL) { - bufsz += wcslen(main_config->module_search_path_env) + 1; + if (calculate->module_search_path_env != NULL) { + bufsz += wcslen(calculate->module_search_path_env) + 1; } wchar_t *defpath = calculate->pythonpath; @@ -857,8 +851,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, buf[0] = '\0'; /* Run-time value of $PYTHONPATH goes first */ - if (main_config->module_search_path_env) { - wcscpy(buf, main_config->module_search_path_env); + if (calculate->module_search_path_env) { + wcscpy(buf, calculate->module_search_path_env); wcscat(buf, delimiter); } @@ -909,6 +903,10 @@ static _PyInitError calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) { + calculate->home = main_config->home; + calculate->module_search_path_env = main_config->module_search_path_env; + calculate->program_name = main_config->program_name; + size_t len; char *path = getenv("PATH"); if (path) { @@ -950,12 +948,9 @@ calculate_free(PyCalculatePath *calculate) static _PyInitError -calculate_path_impl(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, _PyPathConfig *config) +calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) { - _PyInitError err; - - err = calculate_program_full_path(main_config, calculate, config); + _PyInitError err = calculate_program_full_path(calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -969,13 +964,13 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); - calculate_prefix(main_config, calculate, prefix); + calculate_prefix(calculate, prefix); calculate_zip_path(calculate, prefix); wchar_t exec_prefix[MAXPATHLEN+1]; memset(exec_prefix, 0, sizeof(exec_prefix)); - calculate_exec_prefix(main_config, calculate, exec_prefix); + calculate_exec_prefix(calculate, exec_prefix); if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !Py_FrozenFlag) @@ -984,8 +979,8 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, "Consider setting $PYTHONHOME to [:]\n"); } - err = calculate_module_search_path(main_config, calculate, - prefix, exec_prefix, config); + err = calculate_module_search_path(calculate, prefix, exec_prefix, + config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1008,10 +1003,33 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, } +static void +pathconfig_clear(_PyPathConfig *config) +{ +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->prefix); + CLEAR(config->exec_prefix); + CLEAR(config->program_full_path); + CLEAR(config->module_search_path); +#undef CLEAR +} + + +/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() + and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Calculate(_PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) { + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return _Py_INIT_OK(); + } + PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); @@ -1020,11 +1038,16 @@ _PyPathConfig_Calculate(_PyPathConfig *config, goto done; } - err = calculate_path_impl(main_config, &calculate, config); + _PyPathConfig new_path_config; + memset(&new_path_config, 0, sizeof(new_path_config)); + + err = calculate_path_impl(&calculate, &new_path_config); if (_Py_INIT_FAILED(err)) { + pathconfig_clear(&new_path_config); goto done; } + _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: @@ -1032,6 +1055,88 @@ _PyPathConfig_Calculate(_PyPathConfig *config, return err; } + +static void +pathconfig_global_init(void) +{ + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + + _PyInitError err; + _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + + err = _PyMainInterpreterConfig_ReadEnv(&config); + if (!_Py_INIT_FAILED(err)) { + err = _PyPathConfig_Init(&config); + } + _PyMainInterpreterConfig_Clear(&config); + + if (_Py_INIT_FAILED(err)) { + _Py_FatalInitError(err); + } +} + + +void +_PyPathConfig_Fini(void) +{ + pathconfig_clear(&_Py_path_config); +} + + +/* External interface */ +void +Py_SetPath(const wchar_t *path) +{ + if (path == NULL) { + pathconfig_clear(&_Py_path_config); + return; + } + + _PyPathConfig new_config; + new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); + new_config.exec_prefix = _PyMem_RawWcsdup(L""); + new_config.prefix = _PyMem_RawWcsdup(L""); + new_config.module_search_path = _PyMem_RawWcsdup(path); + + pathconfig_clear(&_Py_path_config); + _Py_path_config = new_config; +} + + +wchar_t * +Py_GetPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.module_search_path; +} + + +wchar_t * +Py_GetPrefix(void) +{ + pathconfig_global_init(); + return _Py_path_config.prefix; +} + + +wchar_t * +Py_GetExecPrefix(void) +{ + pathconfig_global_init(); + return _Py_path_config.exec_prefix; +} + + +wchar_t * +Py_GetProgramFullPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.program_full_path; +} + #ifdef __cplusplus } #endif diff --git a/Modules/main.c b/Modules/main.c index 84706e1e290..e9d524a1463 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -412,6 +412,7 @@ typedef struct { /* non-zero if filename, command (-c) or module (-m) is set on the command line */ int run_code; + wchar_t *program_name; /* Error message if a function failed */ _PyInitError err; /* PYTHONWARNINGS env var */ @@ -428,6 +429,7 @@ typedef struct { .config = _PyMainInterpreterConfig_INIT, \ .main_importer_path = NULL, \ .run_code = -1, \ + .program_name = NULL, \ .err = _Py_INIT_OK(), \ .env_warning_options = {0, NULL}} @@ -453,6 +455,7 @@ pymain_free_impl(_PyMain *pymain) pymain_optlist_clear(&pymain->env_warning_options); Py_CLEAR(pymain->main_importer_path); + PyMem_RawFree(pymain->program_name); _PyMainInterpreterConfig_Clear(&pymain->config); @@ -871,21 +874,14 @@ pymain_init_stdio(_PyMain *pymain) /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ - environment variables on macOS if available. */ -static _PyInitError -config_get_program_name(_PyMainInterpreterConfig *config) -{ - assert(config->program_name == NULL); - - /* If Py_SetProgramName() was called, use its value */ - wchar_t *program_name = _Py_path_config.program_name; - if (program_name != NULL) { - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } + environment variables on macOS if available, use argv[0] by default. + Return 0 on success. + Set pymain->err and return -1 on error. */ +static int +pymain_get_program_name(_PyMain *pymain) +{ + assert(pymain->program_name == NULL); #ifdef __APPLE__ char *p; /* On MacOS X, when the Python interpreter is embedded in an @@ -898,13 +894,17 @@ config_get_program_name(_PyMainInterpreterConfig *config) See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') { - size_t len; - wchar_t* program_name = Py_DecodeLocale(p, &len); - if (program_name == NULL) { - return SET_DECODE_ERROR("PYTHONEXECUTABLE environment " - "variable", len); + wchar_t* buffer; + size_t len = strlen(p) + 1; + + buffer = PyMem_RawMalloc(len * sizeof(wchar_t)); + if (buffer == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; } - config->program_name = program_name; + + mbstowcs(buffer, p, len); + pymain->program_name = buffer; } #ifdef WITH_NEXT_FRAMEWORK else { @@ -914,30 +914,21 @@ config_get_program_name(_PyMainInterpreterConfig *config) * the argv0 of the stub executable */ size_t len; - wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len); - if (program_name == NULL) { - return SET_DECODE_ERROR("__PYVENV_LAUNCHER__ environment " - "variable", len); + wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len); + if (wbuf == NULL) { + SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len); + return -1; } - config->program_name = program_name; + pymain->program_name = wbuf; } } #endif /* WITH_NEXT_FRAMEWORK */ #endif /* __APPLE__ */ - return _Py_INIT_OK(); -} - - -/* If config_get_program_name() found no program name: use argv[0] by default. - Return 0 on success. Set pymain->err and return -1 on error. */ -static int -pymain_get_program_name(_PyMain *pymain) -{ - if (pymain->config.program_name == NULL) { + if (pymain->program_name == NULL) { /* Use argv[0] by default */ - pymain->config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); - if (pymain->config.program_name == NULL) { + pymain->program_name = pymain_wstrdup(pymain, pymain->argv[0]); + if (pymain->program_name == NULL) { return -1; } } @@ -959,6 +950,13 @@ pymain_init_main_interpreter(_PyMain *pymain) { _PyInitError err; + /* TODO: Print any exceptions raised by these operations */ + err = _PyMainInterpreterConfig_Read(&pymain->config); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; + return -1; + } + err = _Py_InitializeMainInterpreter(&pymain->config); if (_Py_INIT_FAILED(err)) { pymain->err = err; @@ -1416,13 +1414,14 @@ config_init_pythonpath(_PyMainInterpreterConfig *config) static _PyInitError -config_init_home(_PyMainInterpreterConfig *config) +config_init_pythonhome(_PyMainInterpreterConfig *config) { wchar_t *home; - /* If Py_SetPythonHome() was called, use its value */ - home = _Py_path_config.home; + home = Py_GetPythonHome(); if (home) { + /* Py_SetPythonHome() has been called before Py_Main(), + use its value */ config->home = _PyMem_RawWcsdup(home); if (config->home == NULL) { return _Py_INIT_NO_MEMORY(); @@ -1442,7 +1441,7 @@ config_init_home(_PyMainInterpreterConfig *config) _PyInitError _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) { - _PyInitError err = config_init_home(config); + _PyInitError err = config_init_pythonhome(config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1452,9 +1451,11 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) return err; } - err = config_get_program_name(config); - if (_Py_INIT_FAILED(err)) { - return err; + /* FIXME: _PyMainInterpreterConfig_Read() has the same code. Remove it + here? See also pymain_get_program_name() and pymain_parse_envvars(). */ + config->program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -1480,17 +1481,25 @@ pymain_parse_envvars(_PyMain *pymain) if (pymain_warnings_envvar(pymain) < 0) { return -1; } + if (pymain_get_program_name(pymain) < 0) { + return -1; + } + core_config->allocator = Py_GETENV("PYTHONMALLOC"); + + /* FIXME: move pymain_get_program_name() code into + _PyMainInterpreterConfig_ReadEnv(). + Problem: _PyMainInterpreterConfig_ReadEnv() doesn't have access + to argv[0]. */ + Py_SetProgramName(pymain->program_name); + /* Don't free program_name here: the argument to Py_SetProgramName + must remain valid until Py_FinalizeEx is called. The string is freed + by pymain_free(). */ _PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config); if (_Py_INIT_FAILED(pymain->err)) { pymain->err = err; return -1; } - if (pymain_get_program_name(pymain) < 0) { - return -1; - } - - core_config->allocator = Py_GETENV("PYTHONMALLOC"); /* -X options */ if (pymain_get_xoption(pymain, L"showrefcount")) { @@ -1546,12 +1555,6 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) return -1; } - _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config); - if (_Py_INIT_FAILED(err)) { - pymain->err = err; - return -1; - } - return 0; } @@ -1668,14 +1671,6 @@ pymain_impl(_PyMain *pymain) other special meaning */ pymain->status = 120; } - - /* _PyPathConfig_Clear() cannot be called in Py_FinalizeEx(). - Py_Initialize() and Py_Finalize() can be called multiple times, but it - must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or - Py_SetPythonHome(), whereas _PyPathConfig_Clear() clear all these - parameters. */ - _PyPathConfig_Clear(&_Py_path_config); - return 0; } diff --git a/PC/getpathp.c b/PC/getpathp.c index 08ed8ccc83f..ad04b6b6efc 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -118,6 +118,7 @@ #endif typedef struct { + wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ wchar_t *path_env; /* PATH environment variable */ wchar_t *home; /* PYTHONHOME environment variable */ @@ -125,11 +126,15 @@ typedef struct { wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */ wchar_t *user_path; /* from HKEY_CURRENT_USER */ + wchar_t *program_name; /* Program name */ wchar_t argv0_path[MAXPATHLEN+1]; wchar_t zip_path[MAXPATHLEN+1]; } PyCalculatePath; +static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; + + /* determine if "ch" is a separator character */ static int is_sep(wchar_t ch) @@ -498,8 +503,7 @@ get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) static _PyInitError -get_program_full_path(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, _PyPathConfig *config) +get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); @@ -514,13 +518,12 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, * $PATH isn't exported, you lose. */ #ifdef ALTSEP - if (wcschr(main_config->program_name, SEP) || - wcschr(main_config->program_name, ALTSEP)) + if (wcschr(calculate->program_name, SEP) || wcschr(calculate->program_name, ALTSEP)) #else - if (wcschr(main_config->program_name, SEP)) + if (wcschr(calculate->program_name, SEP)) #endif { - wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); + wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); } else if (calculate->path_env) { wchar_t *path = calculate->path_env; @@ -539,7 +542,7 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, main_config->program_name); + join(program_full_path, calculate->program_name); if (exists(program_full_path)) { break; } @@ -710,6 +713,9 @@ calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) { calculate->home = main_config->home; + calculate->module_search_path_env = main_config->module_search_path_env; + calculate->program_name = main_config->program_name; + calculate->path_env = _wgetenv(L"PATH"); } @@ -718,16 +724,12 @@ static int get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) { if (config->dll_path[0]) { - if (!change_ext(spbuffer, config->dll_path, L"._pth") && - exists(spbuffer)) - { + if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) { return 1; } } if (config->program_full_path[0]) { - if (!change_ext(spbuffer, config->program_full_path, L"._pth") && - exists(spbuffer)) - { + if (!change_ext(spbuffer, config->program_full_path, L"._pth") && exists(spbuffer)) { return 1; } } @@ -813,9 +815,7 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) static _PyInitError -calculate_module_search_path(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, _PyPathConfig *config, - wchar_t *prefix) +calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) { int skiphome = calculate->home==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED @@ -824,10 +824,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (main_config->module_search_path_env != NULL || - calculate->home != NULL || - calculate->machine_path != NULL || - calculate->user_path != NULL); + int skipdefault = (calculate->module_search_path_env!=NULL || calculate->home!=NULL || \ + calculate->machine_path!=NULL || calculate->user_path!=NULL); /* We need to construct a path from the following parts. (1) the PYTHONPATH environment variable, if set; @@ -863,8 +861,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, bufsz += wcslen(calculate->machine_path) + 1; } bufsz += wcslen(calculate->zip_path) + 1; - if (main_config->module_search_path_env != NULL) { - bufsz += wcslen(main_config->module_search_path_env) + 1; + if (calculate->module_search_path_env != NULL) { + bufsz += wcslen(calculate->module_search_path_env) + 1; } wchar_t *buf, *start_buf; @@ -872,9 +870,9 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, if (buf == NULL) { /* We can't exit, so print a warning and limp along */ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); - if (main_config->module_search_path_env) { + if (calculate->module_search_path_env) { fprintf(stderr, "Using environment $PYTHONPATH.\n"); - config->module_search_path = main_config->module_search_path_env; + config->module_search_path = calculate->module_search_path_env; } else { fprintf(stderr, "Using default static path.\n"); @@ -884,9 +882,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, } start_buf = buf; - if (main_config->module_search_path_env) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), - main_config->module_search_path_env)) { + if (calculate->module_search_path_env) { + if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -999,8 +996,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, static _PyInitError -calculate_path_impl(const _PyMainInterpreterConfig *main_config, - PyCalculatePath *calculate, _PyPathConfig *config) +calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, + const _PyMainInterpreterConfig *main_config) { _PyInitError err; @@ -1009,7 +1006,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, return err; } - err = get_program_full_path(main_config, calculate, config); + err = get_program_full_path(calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1035,7 +1032,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, calculate_home_prefix(calculate, prefix); - err = calculate_module_search_path(main_config, calculate, config, prefix); + err = calculate_module_search_path(calculate, config, prefix); if (_Py_INIT_FAILED(err)) { return err; } @@ -1058,28 +1055,145 @@ calculate_free(PyCalculatePath *calculate) } +static void +pathconfig_clear(_PyPathConfig *config) +{ +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->prefix); + CLEAR(config->program_full_path); + CLEAR(config->dll_path); + CLEAR(config->module_search_path); +#undef CLEAR +} + + +/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() + and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Calculate(_PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) { + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return _Py_INIT_OK(); + } + + _PyInitError err; + PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); calculate_init(&calculate, main_config); - _PyInitError err = calculate_path_impl(main_config, &calculate, config); + _PyPathConfig new_path_config; + memset(&new_path_config, 0, sizeof(new_path_config)); + + err = calculate_path_impl(&calculate, &new_path_config, main_config); if (_Py_INIT_FAILED(err)) { goto done; } + _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: + if (_Py_INIT_FAILED(err)) { + pathconfig_clear(&new_path_config); + } calculate_free(&calculate); return err; } +static void +pathconfig_global_init(void) +{ + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + + _PyInitError err; + _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + + err = _PyMainInterpreterConfig_ReadEnv(&config); + if (!_Py_INIT_FAILED(err)) { + err = _PyPathConfig_Init(&config); + } + _PyMainInterpreterConfig_Clear(&config); + + if (_Py_INIT_FAILED(err)) { + _Py_FatalInitError(err); + } +} + + +void +_PyPathConfig_Fini(void) +{ + pathconfig_clear(&_Py_path_config); +} + + +/* External interface */ + +void +Py_SetPath(const wchar_t *path) +{ + if (_Py_path_config.module_search_path != NULL) { + pathconfig_clear(&_Py_path_config); + } + + if (path == NULL) { + return; + } + + _PyPathConfig new_config; + new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); + new_config.prefix = _PyMem_RawWcsdup(L""); + new_config.dll_path = _PyMem_RawWcsdup(L""); + new_config.module_search_path = _PyMem_RawWcsdup(path); + + pathconfig_clear(&_Py_path_config); + _Py_path_config = new_config; +} + + +wchar_t * +Py_GetPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.module_search_path; +} + + +wchar_t * +Py_GetPrefix(void) +{ + pathconfig_global_init(); + return _Py_path_config.prefix; +} + + +wchar_t * +Py_GetExecPrefix(void) +{ + return Py_GetPrefix(); +} + + +wchar_t * +Py_GetProgramFullPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.program_full_path; +} + + /* Load python3.dll before loading any extension module that might refer to it. That way, we can be sure that always the python3.dll corresponding to this python DLL is loaded, not a python3.dll that might be on the path @@ -1089,7 +1203,7 @@ _PyPathConfig_Calculate(_PyPathConfig *config, static int python3_checked = 0; static HANDLE hPython3; int -_Py_CheckPython3(void) +_Py_CheckPython3() { wchar_t py3path[MAXPATHLEN+1]; wchar_t *s; diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index b430e05b629..3793cbda882 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -381,7 +381,6 @@ - diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index c9aa3da355e..1d33c6e2cc2 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -896,9 +896,6 @@ Python - - Python - Python diff --git a/Python/pathconfig.c b/Python/pathconfig.c deleted file mode 100644 index 6a03f7dca1b..00000000000 --- a/Python/pathconfig.c +++ /dev/null @@ -1,266 +0,0 @@ -/* Path configuration like module_search_path (sys.path) */ - -#include "Python.h" -#include "osdefs.h" -#include "internal/pystate.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -_PyPathConfig _Py_path_config = _PyPathConfig_INIT; - - -void -_PyPathConfig_Clear(_PyPathConfig *config) -{ - /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator, - since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be - called before Py_Initialize() which can changes the memory allocator. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - -#define CLEAR(ATTR) \ - do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ - } while (0) - - CLEAR(config->prefix); - CLEAR(config->program_full_path); -#ifdef MS_WINDOWS - CLEAR(config->dll_path); -#else - CLEAR(config->exec_prefix); -#endif - CLEAR(config->module_search_path); - CLEAR(config->home); - CLEAR(config->program_name); -#undef CLEAR - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); -} - - -/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() - and Py_GetProgramFullPath() */ -_PyInitError -_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) -{ - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return _Py_INIT_OK(); - } - - _PyInitError err; - _PyPathConfig new_config = _PyPathConfig_INIT; - - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - /* Calculate program_full_path, prefix, exec_prefix (Unix) - or dll_path (Windows), and module_search_path */ - err = _PyPathConfig_Calculate(&new_config, main_config); - if (_Py_INIT_FAILED(err)) { - _PyPathConfig_Clear(&new_config); - goto done; - } - - /* Copy home and program_name from main_config */ - if (main_config->home != NULL) { - new_config.home = _PyMem_RawWcsdup(main_config->home); - if (new_config.home == NULL) { - err = _Py_INIT_NO_MEMORY(); - goto done; - } - } - else { - new_config.home = NULL; - } - - new_config.program_name = _PyMem_RawWcsdup(main_config->program_name); - if (new_config.program_name == NULL) { - err = _Py_INIT_NO_MEMORY(); - goto done; - } - - _PyPathConfig_Clear(&_Py_path_config); - _Py_path_config = new_config; - - err = _Py_INIT_OK(); - -done: - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return err; -} - - -static void -pathconfig_global_init(void) -{ - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return; - } - - _PyInitError err; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; - - err = _PyMainInterpreterConfig_ReadEnv(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - err = _PyMainInterpreterConfig_Read(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - err = _PyPathConfig_Init(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - - _PyMainInterpreterConfig_Clear(&config); - return; - -error: - _PyMainInterpreterConfig_Clear(&config); - _Py_FatalInitError(err); -} - - -/* External interface */ - -void -Py_SetPath(const wchar_t *path) -{ - if (path == NULL) { - _PyPathConfig_Clear(&_Py_path_config); - return; - } - - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - _PyPathConfig new_config; - new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); - new_config.prefix = _PyMem_RawWcsdup(L""); -#ifdef MS_WINDOWS - new_config.dll_path = _PyMem_RawWcsdup(L""); -#else - new_config.exec_prefix = _PyMem_RawWcsdup(L""); -#endif - new_config.module_search_path = _PyMem_RawWcsdup(path); - - /* steal the home and program_name values (to leave them unchanged) */ - new_config.home = _Py_path_config.home; - _Py_path_config.home = NULL; - new_config.program_name = _Py_path_config.program_name; - _Py_path_config.program_name = NULL; - - _PyPathConfig_Clear(&_Py_path_config); - _Py_path_config = new_config; - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); -} - - -void -Py_SetPythonHome(wchar_t *home) -{ - if (home == NULL) { - return; - } - - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - PyMem_RawFree(_Py_path_config.home); - _Py_path_config.home = _PyMem_RawWcsdup(home); - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - if (_Py_path_config.home == NULL) { - Py_FatalError("Py_SetPythonHome() failed: out of memory"); - } -} - - -void -Py_SetProgramName(wchar_t *program_name) -{ - if (program_name == NULL || program_name[0] == L'\0') { - return; - } - - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - PyMem_RawFree(_Py_path_config.program_name); - _Py_path_config.program_name = _PyMem_RawWcsdup(program_name); - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - if (_Py_path_config.program_name == NULL) { - Py_FatalError("Py_SetProgramName() failed: out of memory"); - } -} - - -wchar_t * -Py_GetPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.module_search_path; -} - - -wchar_t * -Py_GetPrefix(void) -{ - pathconfig_global_init(); - return _Py_path_config.prefix; -} - - -wchar_t * -Py_GetExecPrefix(void) -{ -#ifdef MS_WINDOWS - return Py_GetPrefix(); -#else - pathconfig_global_init(); - return _Py_path_config.exec_prefix; -#endif -} - - -wchar_t * -Py_GetProgramFullPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.program_full_path; -} - - -wchar_t* -Py_GetPythonHome(void) -{ - pathconfig_global_init(); - return _Py_path_config.home; -} - - -wchar_t * -Py_GetProgramName(void) -{ - pathconfig_global_init(); - return _Py_path_config.program_name; -} - - -#ifdef __cplusplus -} -#endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 523397f1269..f0a49f91fb8 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -804,12 +804,7 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) } if (config->program_name == NULL) { -#ifdef MS_WINDOWS - const wchar_t *program_name = L"python"; -#else - const wchar_t *program_name = L"python3"; -#endif - config->program_name = _PyMem_RawWcsdup(program_name); + config->program_name = _PyMem_RawWcsdup(Py_GetProgramName()); if (config->program_name == NULL) { return _Py_INIT_NO_MEMORY(); } @@ -1278,6 +1273,8 @@ Py_FinalizeEx(void) call_ll_exitfuncs(); + _PyPathConfig_Fini(); + _PyRuntime_Finalize(); return status; } @@ -1494,6 +1491,61 @@ Py_EndInterpreter(PyThreadState *tstate) PyInterpreterState_Delete(interp); } +#ifdef MS_WINDOWS +static wchar_t *progname = L"python"; +#else +static wchar_t *progname = L"python3"; +#endif + +void +Py_SetProgramName(wchar_t *pn) +{ + if (pn && *pn) + progname = pn; +} + +wchar_t * +Py_GetProgramName(void) +{ + return progname; +} + +static wchar_t *default_home = NULL; + +void +Py_SetPythonHome(wchar_t *home) +{ + default_home = home; +} + + +wchar_t* +Py_GetPythonHome(void) +{ + /* Use a static buffer to avoid heap memory allocation failure. + Py_GetPythonHome() doesn't allow to report error, and the caller + doesn't release memory. */ + static wchar_t buffer[MAXPATHLEN+1]; + + if (default_home) { + return default_home; + } + + char *home = Py_GETENV("PYTHONHOME"); + if (!home) { + return NULL; + } + + size_t size = Py_ARRAY_LENGTH(buffer); + size_t r = mbstowcs(buffer, home, size); + if (r == (size_t)-1 || r >= size) { + /* conversion failed or the static buffer is too small */ + return NULL; + } + + return buffer; +} + /* Add the __main__ module */ static _PyInitError From webhook-mailer at python.org Sat Dec 2 16:54:03 2017 From: webhook-mailer at python.org (Neil Schemenauer) Date: Sat, 02 Dec 2017 21:54:03 -0000 Subject: [Python-checkins] Add a minimal unit test for Python/frozen.c. (#2995) Message-ID: https://github.com/python/cpython/commit/1eaa1169c522727b1911b798d45c8984992bd179 commit: 1eaa1169c522727b1911b798d45c8984992bd179 branch: master author: Neil Schemenauer committer: GitHub date: 2017-12-02T13:54:00-08:00 summary: Add a minimal unit test for Python/frozen.c. (#2995) If the marshal or bytecode formats get changed, frozen.c needs to be updated as well. It can be easy to miss this step and not doing so can cause test_importlib to crash in mysterious ways. Add an explict unit test to make it easier to track down the problem. files: A Lib/test/test_frozen.py diff --git a/Lib/test/test_frozen.py b/Lib/test/test_frozen.py new file mode 100644 index 00000000000..a7c748422b1 --- /dev/null +++ b/Lib/test/test_frozen.py @@ -0,0 +1,30 @@ +"""Basic test of the frozen module (source is in Python/frozen.c).""" + +# The Python/frozen.c source code contains a marshalled Python module +# and therefore depends on the marshal format as well as the bytecode +# format. If those formats have been changed then frozen.c needs to be +# updated. +# +# The test_importlib also tests this module but because those tests +# are much more complicated, it might be unclear why they are failing. +# Invalid marshalled data in frozen.c could case the interpreter to +# crash when __hello__ is imported. + +import sys +import unittest +from test.support import captured_stdout +from importlib import util + + +class TestFrozen(unittest.TestCase): + def test_frozen(self): + name = '__hello__' + if name in sys.modules: + del sys.modules[name] + with captured_stdout() as out: + import __hello__ + self.assertEqual(out.getvalue(), 'Hello world!\n') + + +if __name__ == '__main__': + unittest.main() From webhook-mailer at python.org Sat Dec 2 17:24:42 2017 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 02 Dec 2017 22:24:42 -0000 Subject: [Python-checkins] bpo-31589 : Build PDF using xelatex for better UTF8 support. (#3940) Message-ID: https://github.com/python/cpython/commit/7324b5ce8e7c031a0a3832a6a8d7c639111ae0ff commit: 7324b5ce8e7c031a0a3832a6a8d7c639111ae0ff branch: master author: Julien Palard committer: Ned Deily date: 2017-12-02T17:24:39-05:00 summary: bpo-31589 : Build PDF using xelatex for better UTF8 support. (#3940) Also addresses doc build failures documented in bpo-32200. files: M Doc/conf.py diff --git a/Doc/conf.py b/Doc/conf.py index aaee983984b..19a2f7d67ff 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -90,11 +90,10 @@ # Options for LaTeX output # ------------------------ +latex_engine = 'xelatex' + # Get LaTeX to handle Unicode correctly latex_elements = { - 'inputenc': r'\usepackage[utf8x]{inputenc}', - 'utf8extra': '', - 'fontenc': r'\usepackage[T1,T2A]{fontenc}', } # Additional stuff for the LaTeX preamble. From webhook-mailer at python.org Sat Dec 2 17:35:11 2017 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 02 Dec 2017 22:35:11 -0000 Subject: [Python-checkins] [3.6] bpo-31589 : Build PDF using xelatex for better UTF8 support. (GH-3940) (#4683) Message-ID: https://github.com/python/cpython/commit/2ad350a713360e89ae6d264924cd28f519b8b22c commit: 2ad350a713360e89ae6d264924cd28f519b8b22c branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2017-12-02T17:35:08-05:00 summary: [3.6] bpo-31589 : Build PDF using xelatex for better UTF8 support. (GH-3940) (#4683) Also addresses doc build failures documented in bpo-32200. (cherry picked from commit 7324b5ce8e7c031a0a3832a6a8d7c639111ae0ff) files: M Doc/conf.py diff --git a/Doc/conf.py b/Doc/conf.py index f7073d116a4..43826ec01f4 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -89,11 +89,10 @@ # Options for LaTeX output # ------------------------ +latex_engine = 'xelatex' + # Get LaTeX to handle Unicode correctly latex_elements = { - 'inputenc': r'\usepackage[utf8x]{inputenc}', - 'utf8extra': '', - 'fontenc': r'\usepackage[T1,T2A]{fontenc}', } # Additional stuff for the LaTeX preamble. From webhook-mailer at python.org Sat Dec 2 20:12:22 2017 From: webhook-mailer at python.org (Nick Coghlan) Date: Sun, 03 Dec 2017 01:12:22 -0000 Subject: [Python-checkins] bpo-32176: Set CO_NOFREE in the code object constructor (GH-4675) Message-ID: https://github.com/python/cpython/commit/078f1814f1a4413a2a0fdb8cf4490ee0fc98ef34 commit: 078f1814f1a4413a2a0fdb8cf4490ee0fc98ef34 branch: master author: Nick Coghlan committer: GitHub date: 2017-12-03T11:12:20+10:00 summary: bpo-32176: Set CO_NOFREE in the code object constructor (GH-4675) Previously, CO_NOFREE was set in the compiler, which meant it could end up being set incorrectly when code objects were created directly. Setting it in the constructor based on freevars and cellvars ensures it is always accurate, regardless of how the code object is defined. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst M Lib/test/test_code.py M Objects/codeobject.c M Python/compile.c diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 90cb584ac40..55faf4c4279 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -102,6 +102,7 @@ """ +import inspect import sys import threading import unittest @@ -130,6 +131,10 @@ def dump(co): print("%s: %s" % (attr, getattr(co, "co_" + attr))) print("consts:", tuple(consts(co.co_consts))) +# Needed for test_closure_injection below +# Defined at global scope to avoid implicitly closing over __class__ +def external_getitem(self, i): + return f"Foreign getitem: {super().__getitem__(i)}" class CodeTest(unittest.TestCase): @@ -141,6 +146,46 @@ def test_newempty(self): self.assertEqual(co.co_name, "funcname") self.assertEqual(co.co_firstlineno, 15) + @cpython_only + def test_closure_injection(self): + # From https://bugs.python.org/issue32176 + from types import FunctionType, CodeType + + def create_closure(__class__): + return (lambda: __class__).__closure__ + + def new_code(c): + '''A new code object with a __class__ cell added to freevars''' + return CodeType( + c.co_argcount, c.co_kwonlyargcount, c.co_nlocals, + c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names, + c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, + c.co_lnotab, c.co_freevars + ('__class__',), c.co_cellvars) + + def add_foreign_method(cls, name, f): + code = new_code(f.__code__) + assert not f.__closure__ + closure = create_closure(cls) + defaults = f.__defaults__ + setattr(cls, name, FunctionType(code, globals(), name, defaults, closure)) + + class List(list): + pass + + add_foreign_method(List, "__getitem__", external_getitem) + + # Ensure the closure injection actually worked + function = List.__getitem__ + class_ref = function.__closure__[0].cell_contents + self.assertIs(class_ref, List) + + # Ensure the code correctly indicates it accesses a free variable + self.assertFalse(function.__code__.co_flags & inspect.CO_NOFREE, + hex(function.__code__.co_flags)) + + # Ensure the zero-arg super() call in the injected method works + obj = List([1, 2, 3]) + self.assertEqual(obj[0], "Foreign getitem: 1") def isinterned(s): return s is sys.intern(('_' + s + '_')[1:-1]) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst new file mode 100644 index 00000000000..9d567112866 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst @@ -0,0 +1,5 @@ +co_flags.CO_NOFREE is now always set correctly by the code object +constructor based on freevars and cellvars, rather than needing to be set +correctly by the caller. This ensures it will be cleared automatically when +additional cell references are injected into a modified code object and +function. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index f312f338a9b..0509b8e6400 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -124,12 +124,20 @@ PyCode_New(int argcount, int kwonlyargcount, if (PyUnicode_READY(filename) < 0) return NULL; - n_cellvars = PyTuple_GET_SIZE(cellvars); intern_strings(names); intern_strings(varnames); intern_strings(freevars); intern_strings(cellvars); intern_string_constants(consts); + + /* Check for any inner or outer closure references */ + n_cellvars = PyTuple_GET_SIZE(cellvars); + if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) { + flags |= CO_NOFREE; + } else { + flags &= ~CO_NOFREE; + } + /* Create mapping between cells and arguments if needed. */ if (n_cellvars) { Py_ssize_t total_args = argcount + kwonlyargcount + diff --git a/Python/compile.c b/Python/compile.c index a3ea60d07c0..a3fcd53e9a2 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -5273,11 +5273,6 @@ compute_code_flags(struct compiler *c) /* (Only) inherit compilerflags in PyCF_MASK */ flags |= (c->c_flags->cf_flags & PyCF_MASK); - if (!PyDict_GET_SIZE(c->u->u_freevars) && - !PyDict_GET_SIZE(c->u->u_cellvars)) { - flags |= CO_NOFREE; - } - return flags; } From solipsis at pitrou.net Sun Dec 3 04:08:23 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 03 Dec 2017 09:08:23 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171203090754.95859.43B3F222D05F1A08@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogxbhPip', '--timeout', '7200'] From webhook-mailer at python.org Sun Dec 3 08:33:02 2017 From: webhook-mailer at python.org (Nick Coghlan) Date: Sun, 03 Dec 2017 13:33:02 -0000 Subject: [Python-checkins] [3.6] bpo-32176: Set CO_NOFREE in the code object constructor (GH-4684) Message-ID: https://github.com/python/cpython/commit/c8f32aae0aa173e122cf4c0592caec620d0d1de9 commit: c8f32aae0aa173e122cf4c0592caec620d0d1de9 branch: 3.6 author: Nick Coghlan committer: GitHub date: 2017-12-03T23:32:54+10:00 summary: [3.6] bpo-32176: Set CO_NOFREE in the code object constructor (GH-4684) Previously, CO_NOFREE was set in the compiler, which meant it could end up being set incorrectly when code objects were created directly. Setting it in the constructor based on freevars and cellvars ensures it is always accurate, regardless of how the code object is defined. (cherry picked from commit 078f1814f1a4413a2a0fdb8cf4490ee0fc98ef34) files: A Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst M Lib/test/test_code.py M Objects/codeobject.c M Python/compile.c diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 90cb584ac40..55faf4c4279 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -102,6 +102,7 @@ """ +import inspect import sys import threading import unittest @@ -130,6 +131,10 @@ def dump(co): print("%s: %s" % (attr, getattr(co, "co_" + attr))) print("consts:", tuple(consts(co.co_consts))) +# Needed for test_closure_injection below +# Defined at global scope to avoid implicitly closing over __class__ +def external_getitem(self, i): + return f"Foreign getitem: {super().__getitem__(i)}" class CodeTest(unittest.TestCase): @@ -141,6 +146,46 @@ def test_newempty(self): self.assertEqual(co.co_name, "funcname") self.assertEqual(co.co_firstlineno, 15) + @cpython_only + def test_closure_injection(self): + # From https://bugs.python.org/issue32176 + from types import FunctionType, CodeType + + def create_closure(__class__): + return (lambda: __class__).__closure__ + + def new_code(c): + '''A new code object with a __class__ cell added to freevars''' + return CodeType( + c.co_argcount, c.co_kwonlyargcount, c.co_nlocals, + c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names, + c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, + c.co_lnotab, c.co_freevars + ('__class__',), c.co_cellvars) + + def add_foreign_method(cls, name, f): + code = new_code(f.__code__) + assert not f.__closure__ + closure = create_closure(cls) + defaults = f.__defaults__ + setattr(cls, name, FunctionType(code, globals(), name, defaults, closure)) + + class List(list): + pass + + add_foreign_method(List, "__getitem__", external_getitem) + + # Ensure the closure injection actually worked + function = List.__getitem__ + class_ref = function.__closure__[0].cell_contents + self.assertIs(class_ref, List) + + # Ensure the code correctly indicates it accesses a free variable + self.assertFalse(function.__code__.co_flags & inspect.CO_NOFREE, + hex(function.__code__.co_flags)) + + # Ensure the zero-arg super() call in the injected method works + obj = List([1, 2, 3]) + self.assertEqual(obj[0], "Foreign getitem: 1") def isinterned(s): return s is sys.intern(('_' + s + '_')[1:-1]) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst new file mode 100644 index 00000000000..9d567112866 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-02-21-37-22.bpo-32176.Wt25-N.rst @@ -0,0 +1,5 @@ +co_flags.CO_NOFREE is now always set correctly by the code object +constructor based on freevars and cellvars, rather than needing to be set +correctly by the caller. This ensures it will be cleared automatically when +additional cell references are injected into a modified code object and +function. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index d45be4c9679..d1c3abf4861 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -136,12 +136,20 @@ PyCode_New(int argcount, int kwonlyargcount, if (PyUnicode_READY(filename) < 0) return NULL; - n_cellvars = PyTuple_GET_SIZE(cellvars); intern_strings(names); intern_strings(varnames); intern_strings(freevars); intern_strings(cellvars); intern_string_constants(consts); + + /* Check for any inner or outer closure references */ + n_cellvars = PyTuple_GET_SIZE(cellvars); + if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) { + flags |= CO_NOFREE; + } else { + flags &= ~CO_NOFREE; + } + /* Create mapping between cells and arguments if needed. */ if (n_cellvars) { Py_ssize_t total_args = argcount + kwonlyargcount + diff --git a/Python/compile.c b/Python/compile.c index 797a1840e6a..4d525a02c81 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -5190,18 +5190,6 @@ compute_code_flags(struct compiler *c) /* (Only) inherit compilerflags in PyCF_MASK */ flags |= (c->c_flags->cf_flags & PyCF_MASK); - n = PyDict_Size(c->u->u_freevars); - if (n < 0) - return -1; - if (n == 0) { - n = PyDict_Size(c->u->u_cellvars); - if (n < 0) - return -1; - if (n == 0) { - flags |= CO_NOFREE; - } - } - return flags; } From webhook-mailer at python.org Sun Dec 3 12:26:09 2017 From: webhook-mailer at python.org (Neil Schemenauer) Date: Sun, 03 Dec 2017 17:26:09 -0000 Subject: [Python-checkins] Refactor PyImport_ImportModuleLevelObject(). (#4680) Message-ID: https://github.com/python/cpython/commit/eea3cc1ef0dec0af193eedb4c1164263fbdfd8cc commit: eea3cc1ef0dec0af193eedb4c1164263fbdfd8cc branch: master author: Neil Schemenauer committer: GitHub date: 2017-12-03T09:26:03-08:00 summary: Refactor PyImport_ImportModuleLevelObject(). (#4680) Add import_find_and_load() helper function. The addition of the importtime option has made PyImport_ImportModuleLevelObject() large and so using a helper seems worthwhile. It also makes it clearer that abs_name is the only argument needed by _find_and_load(). files: M Python/import.c diff --git a/Python/import.c b/Python/import.c index d2ed785c9f9..57521e49207 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1589,12 +1589,67 @@ resolve_name(PyObject *name, PyObject *globals, int level) return NULL; } +static PyObject * +import_find_and_load(PyObject *abs_name) +{ + _Py_IDENTIFIER(_find_and_load); + PyObject *mod = NULL; + PyInterpreterState *interp = PyThreadState_GET()->interp; + int import_time = interp->core_config.import_time; + static int import_level; + static _PyTime_t accumulated; + + _PyTime_t t1 = 0, accumulated_copy = accumulated; + + /* XOptions is initialized after first some imports. + * So we can't have negative cache before completed initialization. + * Anyway, importlib._find_and_load is much slower than + * _PyDict_GetItemIdWithError(). + */ + if (import_time) { + static int header = 1; + if (header) { + fputs("import time: self [us] | cumulative | imported package\n", + stderr); + header = 0; + } + + import_level++; + t1 = _PyTime_GetPerfCounter(); + accumulated = 0; + } + + if (PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()) + PyDTrace_IMPORT_FIND_LOAD_START(PyUnicode_AsUTF8(abs_name)); + + mod = _PyObject_CallMethodIdObjArgs(interp->importlib, + &PyId__find_and_load, abs_name, + interp->import_func, NULL); + + if (PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED()) + PyDTrace_IMPORT_FIND_LOAD_DONE(PyUnicode_AsUTF8(abs_name), + mod != NULL); + + if (import_time) { + _PyTime_t cum = _PyTime_GetPerfCounter() - t1; + + import_level--; + fprintf(stderr, "import time: %9ld | %10ld | %*s%s\n", + (long)_PyTime_AsMicroseconds(cum - accumulated, _PyTime_ROUND_CEILING), + (long)_PyTime_AsMicroseconds(cum, _PyTime_ROUND_CEILING), + import_level*2, "", PyUnicode_AsUTF8(abs_name)); + + accumulated = accumulated_copy + cum; + } + + return mod; +} + PyObject * PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { - _Py_IDENTIFIER(_find_and_load); _Py_IDENTIFIER(_handle_fromlist); PyObject *abs_name = NULL; PyObject *final_mod = NULL; @@ -1674,55 +1729,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } } else { - int import_time = interp->core_config.import_time; - static int import_level; - static _PyTime_t accumulated; - - _PyTime_t t1 = 0, accumulated_copy = accumulated; - - /* XOptions is initialized after first some imports. - * So we can't have negative cache before completed initialization. - * Anyway, importlib._find_and_load is much slower than - * _PyDict_GetItemIdWithError(). - */ - if (import_time) { - static int header = 1; - if (header) { - fputs("import time: self [us] | cumulative | imported package\n", - stderr); - header = 0; - } - - import_level++; - t1 = _PyTime_GetPerfCounter(); - accumulated = 0; - } - - Py_XDECREF(mod); - - if (PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()) - PyDTrace_IMPORT_FIND_LOAD_START(PyUnicode_AsUTF8(abs_name)); - - mod = _PyObject_CallMethodIdObjArgs(interp->importlib, - &PyId__find_and_load, abs_name, - interp->import_func, NULL); - - if (PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED()) - PyDTrace_IMPORT_FIND_LOAD_DONE(PyUnicode_AsUTF8(abs_name), - mod != NULL); - - if (import_time) { - _PyTime_t cum = _PyTime_GetPerfCounter() - t1; - - import_level--; - fprintf(stderr, "import time: %9ld | %10ld | %*s%s\n", - (long)_PyTime_AsMicroseconds(cum - accumulated, _PyTime_ROUND_CEILING), - (long)_PyTime_AsMicroseconds(cum, _PyTime_ROUND_CEILING), - import_level*2, "", PyUnicode_AsUTF8(abs_name)); - - accumulated = accumulated_copy + cum; - } - + mod = import_find_and_load(abs_name); if (mod == NULL) { goto error; } From webhook-mailer at python.org Sun Dec 3 15:12:16 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 03 Dec 2017 20:12:16 -0000 Subject: [Python-checkins] bpo-32137: The repr of deeply nested dict now raises a RecursionError (#4570) Message-ID: https://github.com/python/cpython/commit/1fb72d2ad243c965d4432b4e93884064001a2607 commit: 1fb72d2ad243c965d4432b4e93884064001a2607 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-03T22:12:11+02:00 summary: bpo-32137: The repr of deeply nested dict now raises a RecursionError (#4570) instead of crashing due to a stack overflow. This perhaps will fix similar problems in other extension types. files: A Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst M Lib/test/list_tests.py M Lib/test/mapping_tests.py M Lib/test/test_dict.py M Objects/listobject.c M Objects/object.c M Objects/tupleobject.c diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py index ce9db9a1b8b..ed63fda20c1 100644 --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -53,10 +53,11 @@ def test_repr(self): self.assertEqual(str(a2), "[0, 1, 2, [...], 3]") self.assertEqual(repr(a2), "[0, 1, 2, [...], 3]") - l0 = [] + def test_repr_deep(self): + a = self.type2test([]) for i in range(sys.getrecursionlimit() + 100): - l0 = [l0] - self.assertRaises(RecursionError, repr, l0) + a = self.type2test([a]) + self.assertRaises(RecursionError, repr, a) def test_print(self): d = self.type2test(range(200)) diff --git a/Lib/test/mapping_tests.py b/Lib/test/mapping_tests.py index ff82f4eb7d8..53f29f60538 100644 --- a/Lib/test/mapping_tests.py +++ b/Lib/test/mapping_tests.py @@ -1,6 +1,7 @@ # tests common to dict and UserDict import unittest import collections +import sys class BasicTestMappingProtocol(unittest.TestCase): @@ -619,6 +620,14 @@ def __repr__(self): d = self._full_mapping({1: BadRepr()}) self.assertRaises(Exc, repr, d) + def test_repr_deep(self): + d = self._empty_mapping() + for i in range(sys.getrecursionlimit() + 100): + d0 = d + d = self._empty_mapping() + d[1] = d0 + self.assertRaises(RecursionError, repr, d) + def test_eq(self): self.assertEqual(self._empty_mapping(), self._empty_mapping()) self.assertEqual(self._full_mapping({1: 2}), diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 8013f37c88d..4386eda3ae4 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -468,6 +468,12 @@ def __repr__(self): d = {1: BadRepr()} self.assertRaises(Exc, repr, d) + def test_repr_deep(self): + d = {} + for i in range(sys.getrecursionlimit() + 100): + d = {1: d} + self.assertRaises(RecursionError, repr, d) + def test_eq(self): self.assertEqual({}, {}) self.assertEqual({1: 2}, {1: 2}) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst new file mode 100644 index 00000000000..f8f4ab93c9e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst @@ -0,0 +1,2 @@ +The repr of deeply nested dict now raises a RecursionError instead of +crashing due to a stack overflow. diff --git a/Objects/listobject.c b/Objects/listobject.c index 8576b7ae683..8794e37364a 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -364,10 +364,7 @@ list_repr(PyListObject *v) goto error; } - if (Py_EnterRecursiveCall(" while getting the repr of a list")) - goto error; s = PyObject_Repr(v->ob_item[i]); - Py_LeaveRecursiveCall(); if (s == NULL) goto error; diff --git a/Objects/object.c b/Objects/object.c index 674180d7203..a0d651d0805 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -463,7 +463,12 @@ PyObject_Repr(PyObject *v) assert(!PyErr_Occurred()); #endif + /* It is possible for a type to have a tp_repr representation that loops + infinitely. */ + if (Py_EnterRecursiveCall(" while getting the repr of an object")) + return NULL; res = (*v->ob_type->tp_repr)(v); + Py_LeaveRecursiveCall(); if (res == NULL) return NULL; if (!PyUnicode_Check(res)) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 964db3bb8de..3a609461251 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -303,10 +303,7 @@ tuplerepr(PyTupleObject *v) goto error; } - if (Py_EnterRecursiveCall(" while getting the repr of a tuple")) - goto error; s = PyObject_Repr(v->ob_item[i]); - Py_LeaveRecursiveCall(); if (s == NULL) goto error; From webhook-mailer at python.org Sun Dec 3 15:16:24 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 03 Dec 2017 20:16:24 -0000 Subject: [Python-checkins] bpo-31619: Fixed integer overflow in converting huge strings to int. (#3884) Message-ID: https://github.com/python/cpython/commit/29ba688034fc4eef0693b86002cf7bee55d692af commit: 29ba688034fc4eef0693b86002cf7bee55d692af branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-03T22:16:21+02:00 summary: bpo-31619: Fixed integer overflow in converting huge strings to int. (#3884) files: M Objects/longobject.c diff --git a/Objects/longobject.c b/Objects/longobject.c index c3dc59ee9e9..a7f496825eb 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2024,7 +2024,7 @@ long_from_binary_base(const char **str, int base, PyLongObject **res) const char *p = *str; const char *start = p; char prev = 0; - int digits = 0; + Py_ssize_t digits = 0; int bits_per_char; Py_ssize_t n; PyLongObject *z; @@ -2267,8 +2267,9 @@ just 1 digit at the start, so that the copying code was exercised for every digit beyond the first. ***/ twodigits c; /* current input character */ + double fsize_z; Py_ssize_t size_z; - int digits = 0; + Py_ssize_t digits = 0; int i; int convwidth; twodigits convmultmax, convmult; @@ -2330,7 +2331,14 @@ digit beyond the first. * need to initialize z->ob_digit -- no slot is read up before * being stored into. */ - size_z = (Py_ssize_t)(digits * log_base_BASE[base]) + 1; + fsize_z = digits * log_base_BASE[base] + 1; + if (fsize_z > MAX_LONG_DIGITS) { + /* The same exception as in _PyLong_New(). */ + PyErr_SetString(PyExc_OverflowError, + "too many digits in integer"); + return NULL; + } + size_z = (Py_ssize_t)fsize_z; /* Uncomment next line to test exceedingly rare copy code */ /* size_z = 1; */ assert(size_z > 0); From webhook-mailer at python.org Sun Dec 3 16:27:24 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 03 Dec 2017 21:27:24 -0000 Subject: [Python-checkins] bpo-31619: Fixed integer overflow in converting huge strings to int. (GH-3884) (#4690) Message-ID: https://github.com/python/cpython/commit/30a6bc842945e3e9c9c7db887ab495c428ec7074 commit: 30a6bc842945e3e9c9c7db887ab495c428ec7074 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-03T23:27:21+02:00 summary: bpo-31619: Fixed integer overflow in converting huge strings to int. (GH-3884) (#4690) (cherry picked from commit 29ba688034fc4eef0693b86002cf7bee55d692af) files: M Objects/longobject.c diff --git a/Objects/longobject.c b/Objects/longobject.c index c0cd7c12be2..c3c0949189d 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2016,7 +2016,7 @@ long_from_binary_base(const char **str, int base, PyLongObject **res) const char *p = *str; const char *start = p; char prev = 0; - int digits = 0; + Py_ssize_t digits = 0; int bits_per_char; Py_ssize_t n; PyLongObject *z; @@ -2259,8 +2259,9 @@ just 1 digit at the start, so that the copying code was exercised for every digit beyond the first. ***/ twodigits c; /* current input character */ + double fsize_z; Py_ssize_t size_z; - int digits = 0; + Py_ssize_t digits = 0; int i; int convwidth; twodigits convmultmax, convmult; @@ -2322,7 +2323,14 @@ digit beyond the first. * need to initialize z->ob_digit -- no slot is read up before * being stored into. */ - size_z = (Py_ssize_t)(digits * log_base_BASE[base]) + 1; + fsize_z = digits * log_base_BASE[base] + 1; + if (fsize_z > MAX_LONG_DIGITS) { + /* The same exception as in _PyLong_New(). */ + PyErr_SetString(PyExc_OverflowError, + "too many digits in integer"); + return NULL; + } + size_z = (Py_ssize_t)fsize_z; /* Uncomment next line to test exceedingly rare copy code */ /* size_z = 1; */ assert(size_z > 0); From webhook-mailer at python.org Sun Dec 3 18:51:44 2017 From: webhook-mailer at python.org (R. David Murray) Date: Sun, 03 Dec 2017 23:51:44 -0000 Subject: [Python-checkins] bpo-27240 Rewrite the email header folding algorithm. (#3488) Message-ID: https://github.com/python/cpython/commit/85d5c18c9d83a1d54eecc4c2ad4dce63194107c6 commit: 85d5c18c9d83a1d54eecc4c2ad4dce63194107c6 branch: master author: R. David Murray committer: GitHub date: 2017-12-03T18:51:41-05:00 summary: bpo-27240 Rewrite the email header folding algorithm. (#3488) The original algorithm tried to delegate the folding to the tokens so that those tokens whose folding rules differed could specify the differences. However, this resulted in a lot of duplicated code because most of the rules were the same. The new algorithm moves all folding logic into a set of functions external to the token classes, but puts the information about which tokens can be folded in which ways on the tokens...with the exception of mime-parameters, which are a special case (which was not even implemented in the old folder). This algorithm can still probably be improved and hopefully simplified somewhat. Note that some of the test expectations are changed. I believe the changes are toward more desirable and consistent behavior: in general when (re) folding a line the canonical version of the tokens is generated, rather than preserving errors or extra whitespace. files: A Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst M Lib/email/_header_value_parser.py M Lib/email/headerregistry.py M Lib/test/test_email/test__header_value_parser.py M Lib/test/test_email/test_generator.py M Lib/test/test_email/test_headerregistry.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index b4737c806e1..b34c58bf85d 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -96,90 +96,6 @@ def quote_string(value): return '"'+str(value).replace('\\', '\\\\').replace('"', r'\"')+'"' -# -# Accumulator for header folding -# - -class _Folded: - - def __init__(self, maxlen, policy): - self.maxlen = maxlen - self.policy = policy - self.lastlen = 0 - self.stickyspace = None - self.firstline = True - self.done = [] - self.current = [] - - def newline(self): - self.done.extend(self.current) - self.done.append(self.policy.linesep) - self.current.clear() - self.lastlen = 0 - - def finalize(self): - if self.current: - self.newline() - - def __str__(self): - return ''.join(self.done) - - def append(self, stoken): - self.current.append(stoken) - - def append_if_fits(self, token, stoken=None): - if stoken is None: - stoken = str(token) - l = len(stoken) - if self.stickyspace is not None: - stickyspace_len = len(self.stickyspace) - if self.lastlen + stickyspace_len + l <= self.maxlen: - self.current.append(self.stickyspace) - self.lastlen += stickyspace_len - self.current.append(stoken) - self.lastlen += l - self.stickyspace = None - self.firstline = False - return True - if token.has_fws: - ws = token.pop_leading_fws() - if ws is not None: - self.stickyspace += str(ws) - stickyspace_len += len(ws) - token._fold(self) - return True - if stickyspace_len and l + 1 <= self.maxlen: - margin = self.maxlen - l - if 0 < margin < stickyspace_len: - trim = stickyspace_len - margin - self.current.append(self.stickyspace[:trim]) - self.stickyspace = self.stickyspace[trim:] - stickyspace_len = trim - self.newline() - self.current.append(self.stickyspace) - self.current.append(stoken) - self.lastlen = l + stickyspace_len - self.stickyspace = None - self.firstline = False - return True - if not self.firstline: - self.newline() - self.current.append(self.stickyspace) - self.current.append(stoken) - self.stickyspace = None - self.firstline = False - return True - if self.lastlen + l <= self.maxlen: - self.current.append(stoken) - self.lastlen += l - return True - if l < self.maxlen: - self.newline() - self.current.append(stoken) - self.lastlen = l - return True - return False - # # TokenList and its subclasses # @@ -187,6 +103,8 @@ def append_if_fits(self, token, stoken=None): class TokenList(list): token_type = None + syntactic_break = True + ew_combine_allowed = True def __init__(self, *args, **kw): super().__init__(*args, **kw) @@ -207,84 +125,13 @@ def value(self): def all_defects(self): return sum((x.all_defects for x in self), self.defects) - # - # Folding API - # - # parts(): - # - # return a list of objects that constitute the "higher level syntactic - # objects" specified by the RFC as the best places to fold a header line. - # The returned objects must include leading folding white space, even if - # this means mutating the underlying parse tree of the object. Each object - # is only responsible for returning *its* parts, and should not drill down - # to any lower level except as required to meet the leading folding white - # space constraint. - # - # _fold(folded): - # - # folded: the result accumulator. This is an instance of _Folded. - # (XXX: I haven't finished factoring this out yet, the folding code - # pretty much uses this as a state object.) When the folded.current - # contains as much text as will fit, the _fold method should call - # folded.newline. - # folded.lastlen: the current length of the test stored in folded.current. - # folded.maxlen: The maximum number of characters that may appear on a - # folded line. Differs from the policy setting in that "no limit" is - # represented by +inf, which means it can be used in the trivially - # logical fashion in comparisons. - # - # Currently no subclasses implement parts, and I think this will remain - # true. A subclass only needs to implement _fold when the generic version - # isn't sufficient. _fold will need to be implemented primarily when it is - # possible for encoded words to appear in the specialized token-list, since - # there is no generic algorithm that can know where exactly the encoded - # words are allowed. A _fold implementation is responsible for filling - # lines in the same general way that the top level _fold does. It may, and - # should, call the _fold method of sub-objects in a similar fashion to that - # of the top level _fold. - # - # XXX: I'm hoping it will be possible to factor the existing code further - # to reduce redundancy and make the logic clearer. - - @property - def parts(self): - klass = self.__class__ - this = [] - for token in self: - if token.startswith_fws(): - if this: - yield this[0] if len(this)==1 else klass(this) - this.clear() - end_ws = token.pop_trailing_ws() - this.append(token) - if end_ws: - yield klass(this) - this = [end_ws] - if this: - yield this[0] if len(this)==1 else klass(this) - def startswith_fws(self): return self[0].startswith_fws() - def pop_leading_fws(self): - if self[0].token_type == 'fws': - return self.pop(0) - return self[0].pop_leading_fws() - - def pop_trailing_ws(self): - if self[-1].token_type == 'cfws': - return self.pop(-1) - return self[-1].pop_trailing_ws() - @property - def has_fws(self): - for part in self: - if part.has_fws: - return True - return False - - def has_leading_comment(self): - return self[0].has_leading_comment() + def as_ew_allowed(self): + """True if all top level tokens of this part may be RFC2047 encoded.""" + return all(part.as_ew_allowed for part in self) @property def comments(self): @@ -294,69 +141,13 @@ def comments(self): return comments def fold(self, *, policy): - # max_line_length 0/None means no limit, ie: infinitely long. - maxlen = policy.max_line_length or float("+inf") - folded = _Folded(maxlen, policy) - self._fold(folded) - folded.finalize() - return str(folded) - - def as_encoded_word(self, charset): - # This works only for things returned by 'parts', which include - # the leading fws, if any, that should be used. - res = [] - ws = self.pop_leading_fws() - if ws: - res.append(ws) - trailer = self.pop(-1) if self[-1].token_type=='fws' else '' - res.append(_ew.encode(str(self), charset)) - res.append(trailer) - return ''.join(res) - - def cte_encode(self, charset, policy): - res = [] - for part in self: - res.append(part.cte_encode(charset, policy)) - 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(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 when utf8 is False. - charset = 'utf-8' - tstr = part.cte_encode(charset, folded.policy) - tlen = len(tstr) - if folded.append_if_fits(part, tstr): - continue - # Peel off the leading whitespace if any and make it sticky, to - # avoid infinite recursion. - ws = part.pop_leading_fws() - if ws is not None: - folded.stickyspace = str(ws) - if folded.append_if_fits(part): - continue - if part.has_fws: - part._fold(folded) - continue - # There are no fold points in this one; it is too long for a single - # line and can't be split...we just have to put it on its own line. - folded.append(tstr) - folded.newline() + return _refold_parse_tree(self, policy=policy) def pprint(self, indent=''): - print('\n'.join(self._pp(indent=''))) + print(self.ppstr(indent=indent)) def ppstr(self, indent=''): - return '\n'.join(self._pp(indent='')) + return '\n'.join(self._pp(indent=indent)) def _pp(self, indent=''): yield '{}{}/{}('.format( @@ -391,173 +182,11 @@ class UnstructuredTokenList(TokenList): token_type = 'unstructured' - 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(encoding) - except UnicodeEncodeError: - if any(isinstance(x, errors.UndecodableBytesDefect) - for x in part.all_defects): - charset = 'unknown-8bit' - else: - charset = 'utf-8' - if last_ew is not None: - # We've already done an EW, combine this one with it - # if there's room. - chunk = get_unstructured( - ''.join(folded.current[last_ew:]+[tstr])).as_encoded_word(charset) - oldlastlen = sum(len(x) for x in folded.current[:last_ew]) - schunk = str(chunk) - lchunk = len(schunk) - if oldlastlen + lchunk <= folded.maxlen: - del folded.current[last_ew:] - folded.append(schunk) - folded.lastlen = oldlastlen + lchunk - continue - tstr = part.as_encoded_word(charset) - is_ew = True - if folded.append_if_fits(part, tstr): - if is_ew: - last_ew = len(folded.current) - 1 - continue - if is_ew or last_ew: - # It's too big to fit on the line, but since we've - # got encoded words we can use encoded word folding. - part._fold_as_ew(folded) - continue - # Peel off the leading whitespace if any and make it sticky, to - # avoid infinite recursion. - ws = part.pop_leading_fws() - if ws is not None: - folded.stickyspace = str(ws) - if folded.append_if_fits(part): - continue - if part.has_fws: - part._fold(folded) - continue - # It can't be split...we just have to put it on its own line. - folded.append(tstr) - folded.newline() - last_ew = None - - def cte_encode(self, charset, policy): - res = [] - last_ew = None - for part in self: - spart = str(part) - try: - spart.encode('us-ascii') - res.append(spart) - except UnicodeEncodeError: - if last_ew is None: - res.append(part.cte_encode(charset, policy)) - last_ew = len(res) - else: - tl = get_unstructured(''.join(res[last_ew:] + [spart])) - res.append(tl.as_encoded_word(charset)) - return ''.join(res) - class Phrase(TokenList): token_type = 'phrase' - def _fold(self, folded): - # As with Unstructured, we can have pure ASCII with or without - # surrogateescape encoded bytes, or we could have unicode. But this - # case is more complicated, since we have to deal with the various - # sub-token types and how they can be composed in the face of - # unicode-that-needs-CTE-encoding, and the fact that if a token a - # 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(encoding) - except UnicodeEncodeError: - if any(isinstance(x, errors.UndecodableBytesDefect) - for x in part.all_defects): - charset = 'unknown-8bit' - else: - charset = 'utf-8' - if last_ew is not None and not part.has_leading_comment(): - # We've already done an EW, let's see if we can combine - # this one with it. The last_ew logic ensures that all we - # have at this point is atoms, no comments or quoted - # strings. So we can treat the text between the last - # encoded word and the content of this token as - # unstructured text, and things will work correctly. But - # we have to strip off any trailing comment on this token - # first, and if it is a quoted string we have to pull out - # the content (we're encoding it, so it no longer needs to - # be quoted). - if part[-1].token_type == 'cfws' and part.comments: - remainder = part.pop(-1) - else: - remainder = '' - for i, token in enumerate(part): - if token.token_type == 'bare-quoted-string': - part[i] = UnstructuredTokenList(token[:]) - chunk = get_unstructured( - ''.join(folded.current[last_ew:]+[tstr])).as_encoded_word(charset) - schunk = str(chunk) - lchunk = len(schunk) - if last_ew + lchunk <= folded.maxlen: - del folded.current[last_ew:] - folded.append(schunk) - folded.lastlen = sum(len(x) for x in folded.current) - continue - tstr = part.as_encoded_word(charset) - tlen = len(tstr) - has_ew = True - if folded.append_if_fits(part, tstr): - if has_ew and not part.comments: - last_ew = len(folded.current) - 1 - elif part.comments or part.token_type == 'quoted-string': - # If a comment is involved we can't combine EWs. And if a - # quoted string is involved, it's not worth the effort to - # try to combine them. - last_ew = None - continue - part._fold(folded) - - def cte_encode(self, charset, policy): - res = [] - last_ew = None - is_ew = False - for part in self: - spart = str(part) - try: - spart.encode('us-ascii') - res.append(spart) - except UnicodeEncodeError: - is_ew = True - if last_ew is None: - if not part.comments: - last_ew = len(res) - res.append(part.cte_encode(charset, policy)) - elif not part.has_leading_comment(): - if part[-1].token_type == 'cfws' and part.comments: - remainder = part.pop(-1) - else: - remainder = '' - for i, token in enumerate(part): - if token.token_type == 'bare-quoted-string': - part[i] = UnstructuredTokenList(token[:]) - tl = get_unstructured(''.join(res[last_ew:] + [spart])) - res[last_ew:] = [tl.as_encoded_word(charset)] - if part.comments or (not is_ew and part.token_type == 'quoted-string'): - last_ew = None - return ''.join(res) - class Word(TokenList): token_type = 'word' @@ -567,9 +196,6 @@ class CFWSList(WhiteSpaceTokenList): token_type = 'cfws' - def has_leading_comment(self): - return bool(self.comments) - class Atom(TokenList): @@ -579,6 +205,7 @@ class Atom(TokenList): class Token(TokenList): token_type = 'token' + encode_as_ew = False class EncodedWord(TokenList): @@ -588,13 +215,6 @@ class EncodedWord(TokenList): charset = None lang = None - @property - def encoded(self): - if self.cte is not None: - return self.cte - _ew.encode(str(self), self.charset) - - class QuotedString(TokenList): @@ -865,6 +485,7 @@ def display_name(self): class Domain(TokenList): token_type = 'domain' + as_ew_allowed = False @property def domain(self): @@ -879,11 +500,13 @@ class DotAtom(TokenList): class DotAtomText(TokenList): token_type = 'dot-atom-text' + as_ew_allowed = True class AddrSpec(TokenList): token_type = 'addr-spec' + as_ew_allowed = False @property def local_part(self): @@ -916,11 +539,13 @@ def addr_spec(self): class ObsLocalPart(TokenList): token_type = 'obs-local-part' + as_ew_allowed = False class DisplayName(Phrase): token_type = 'display-name' + ew_combine_allowed = False @property def display_name(self): @@ -960,6 +585,7 @@ def value(self): class LocalPart(TokenList): token_type = 'local-part' + as_ew_allowed = False @property def value(self): @@ -995,6 +621,7 @@ def local_part(self): class DomainLiteral(TokenList): token_type = 'domain-literal' + as_ew_allowed = False @property def domain(self): @@ -1081,6 +708,7 @@ def stripped_value(self): class MimeParameters(TokenList): token_type = 'mime-parameters' + syntactic_break = False @property def params(self): @@ -1165,6 +793,10 @@ def __str__(self): class ParameterizedHeaderValue(TokenList): + # Set this false so that the value doesn't wind up on a new line even + # if it and the parameters would fit there but not on the first line. + syntactic_break = False + @property def params(self): for token in reversed(self): @@ -1172,18 +804,11 @@ def params(self): return token.params return {} - @property - def parts(self): - if self and self[-1].token_type == 'mime-parameters': - # We don't want to start a new line if all of the params don't fit - # after the value, so unwrap the parameter list. - return TokenList(self[:-1] + self[-1]) - return TokenList(self).parts - class ContentType(ParameterizedHeaderValue): token_type = 'content-type' + as_ew_allowed = False maintype = 'text' subtype = 'plain' @@ -1191,40 +816,27 @@ class ContentType(ParameterizedHeaderValue): class ContentDisposition(ParameterizedHeaderValue): token_type = 'content-disposition' + as_ew_allowed = False content_disposition = None class ContentTransferEncoding(TokenList): token_type = 'content-transfer-encoding' + as_ew_allowed = False cte = '7bit' class HeaderLabel(TokenList): token_type = 'header-label' + as_ew_allowed = False class Header(TokenList): token_type = 'header' - def _fold(self, folded): - folded.append(str(self.pop(0))) - folded.lastlen = len(folded.current[0]) - # The first line of the header is different from all others: we don't - # want to start a new object on a new line if it has any fold points in - # it that would allow part of it to be on the first header line. - # Further, if the first fold point would fit on the new line, we want - # to do that, but if it doesn't we want to put it on the first line. - # Folded supports this via the stickyspace attribute. If this - # attribute is not None, it does the special handling. - folded.stickyspace = str(self.pop(0)) if self[0].token_type == 'cfws' else '' - rest = self.pop(0) - if self: - raise ValueError("Malformed Header token list") - rest._fold(folded) - # # Terminal classes and instances @@ -1232,6 +844,10 @@ def _fold(self, folded): class Terminal(str): + as_ew_allowed = True + ew_combine_allowed = True + syntactic_break = True + def __new__(cls, value, token_type): self = super().__new__(cls, value) self.token_type = token_type @@ -1241,6 +857,9 @@ def __new__(cls, value, token_type): def __repr__(self): return "{}({})".format(self.__class__.__name__, super().__repr__()) + def pprint(self): + print(self.__class__.__name__ + '/' + self.token_type) + @property def all_defects(self): return list(self.defects) @@ -1254,29 +873,14 @@ def _pp(self, indent=''): '' if not self.defects else ' {}'.format(self.defects), )] - def cte_encode(self, charset, policy): - value = str(self) - try: - value.encode('us-ascii') - return value - except UnicodeEncodeError: - return _ew.encode(value, charset) - def pop_trailing_ws(self): # This terminates the recursion. return None - def pop_leading_fws(self): - # This terminates the recursion. - return None - @property def comments(self): return [] - def has_leading_comment(self): - return False - def __getnewargs__(self): return(str(self), self.token_type) @@ -1290,8 +894,6 @@ def value(self): def startswith_fws(self): return True - has_fws = True - class ValueTerminal(Terminal): @@ -1302,11 +904,6 @@ def value(self): def startswith_fws(self): return False - has_fws = False - - def as_encoded_word(self, charset): - return _ew.encode(str(self), charset) - class EWWhiteSpaceTerminal(WhiteSpaceTerminal): @@ -1314,15 +911,9 @@ class EWWhiteSpaceTerminal(WhiteSpaceTerminal): def value(self): return '' - @property - def encoded(self): - return self[:] - def __str__(self): return '' - has_fws = True - # XXX these need to become classes and used as instances so # that a program can't change them in a parse tree and screw @@ -2751,7 +2342,7 @@ def get_parameter(value): if value[0] != "'": raise errors.HeaderParseError("Expected RFC2231 char/lang encoding " "delimiter, but found {!r}".format(value)) - appendto.append(ValueTerminal("'", 'RFC2231 delimiter')) + appendto.append(ValueTerminal("'", 'RFC2231-delimiter')) value = value[1:] if value and value[0] != "'": token, value = get_attrtext(value) @@ -2760,7 +2351,7 @@ def get_parameter(value): if not value or value[0] != "'": raise errors.HeaderParseError("Expected RFC2231 char/lang encoding " "delimiter, but found {}".format(value)) - appendto.append(ValueTerminal("'", 'RFC2231 delimiter')) + appendto.append(ValueTerminal("'", 'RFC2231-delimiter')) value = value[1:] if remainder is not None: # Treat the rest of value as bare quoted string content. @@ -2965,3 +2556,255 @@ def parse_content_transfer_encoding_header(value): token, value = get_phrase(value) cte_header.append(token) return cte_header + + +# +# Header folding +# +# Header folding is complex, with lots of rules and corner cases. The +# following code does its best to obey the rules and handle the corner +# cases, but you can be sure there are few bugs:) +# +# This folder generally canonicalizes as it goes, preferring the stringified +# version of each token. The tokens contain information that supports the +# folder, including which tokens can be encoded in which ways. +# +# Folded text is accumulated in a simple list of strings ('lines'), each +# one of which should be less than policy.max_line_length ('maxlen'). +# + +def _steal_trailing_WSP_if_exists(lines): + wsp = '' + if lines and lines[-1] and lines[-1][-1] in WSP: + wsp = lines[-1][-1] + lines[-1] = lines[-1][:-1] + return wsp + +def _refold_parse_tree(parse_tree, *, policy): + """Return string of contents of parse_tree folded according to RFC rules. + + """ + # max_line_length 0/None means no limit, ie: infinitely long. + maxlen = policy.max_line_length or float("+inf") + encoding = 'utf-8' if policy.utf8 else 'us-ascii' + lines = [''] + last_ew = None + wrap_as_ew_blocked = 0 + want_encoding = False + end_ew_not_allowed = Terminal('', 'wrap_as_ew_blocked') + parts = list(parse_tree) + while parts: + part = parts.pop(0) + if part is end_ew_not_allowed: + wrap_as_ew_blocked -= 1 + continue + tstr = str(part) + try: + tstr.encode(encoding) + charset = encoding + except UnicodeEncodeError: + if any(isinstance(x, errors.UndecodableBytesDefect) + for x in part.all_defects): + charset = 'unknown-8bit' + else: + # If policy.utf8 is false this should really be taken from a + # 'charset' property on the policy. + charset = 'utf-8' + want_encoding = True + if part.token_type == 'mime-parameters': + # Mime parameter folding (using RFC2231) is extra special. + _fold_mime_parameters(part, lines, maxlen, encoding) + continue + if want_encoding and not wrap_as_ew_blocked: + if not part.as_ew_allowed: + want_encoding = False + last_ew = None + if part.syntactic_break: + encoded_part = part.fold(policy=policy)[:-1] # strip nl + if policy.linesep not in encoded_part: + # It fits on a single line + if len(encoded_part) > maxlen - len(lines[-1]): + # But not on this one, so start a new one. + newline = _steal_trailing_WSP_if_exists(lines) + # XXX what if encoded_part has no leading FWS? + lines.append(newline) + lines[-1] += encoded_part + continue + # Either this is not a major syntactic break, so we don't + # want it on a line by itself even if it fits, or it + # doesn't fit on a line by itself. Either way, fall through + # to unpacking the subparts and wrapping them. + if not hasattr(part, 'encode'): + # It's not a Terminal, do each piece individually. + parts = list(part) + parts + else: + # It's a terminal, wrap it as an encoded word, possibly + # combining it with previously encoded words if allowed. + last_ew = _fold_as_ew(tstr, lines, maxlen, last_ew, + part.ew_combine_allowed, charset) + want_encoding = False + continue + if len(tstr) <= maxlen - len(lines[-1]): + lines[-1] += tstr + continue + # This part is too long to fit. The RFC wants us to break at + # "major syntactic breaks", so unless we don't consider this + # to be one, check if it will fit on the next line by itself. + if (part.syntactic_break and + len(tstr) + 1 <= maxlen): + newline = _steal_trailing_WSP_if_exists(lines) + if newline or part.startswith_fws(): + lines.append(newline + tstr) + continue + if not hasattr(part, 'encode'): + # It's not a terminal, try folding the subparts. + newparts = list(part) + if not part.as_ew_allowed: + wrap_as_ew_blocked += 1 + newparts.append(end_ew_not_allowed) + parts = newparts + parts + continue + if part.as_ew_allowed and not wrap_as_ew_blocked: + # It doesn't need CTE encoding, but encode it anyway so we can + # wrap it. + parts.insert(0, part) + want_encoding = True + continue + # We can't figure out how to wrap, it, so give up. + newline = _steal_trailing_WSP_if_exists(lines) + if newline or part.startswith_fws(): + lines.append(newline + tstr) + else: + # We can't fold it onto the next line either... + lines[-1] += tstr + return policy.linesep.join(lines) + policy.linesep + +def _fold_as_ew(to_encode, lines, maxlen, last_ew, ew_combine_allowed, charset): + """Fold string to_encode into lines as encoded word, combining if allowed. + Return the new value for last_ew, or None if ew_combine_allowed is False. + + If there is already an encoded word in the last line of lines (indicated by + a non-None value for last_ew) and ew_combine_allowed is true, decode the + existing ew, combine it with to_encode, and re-encode. Otherwise, encode + to_encode. In either case, split to_encode as necessary so that the + encoded segments fit within maxlen. + + """ + if last_ew is not None and ew_combine_allowed: + to_encode = str( + get_unstructured(lines[-1][last_ew:] + to_encode)) + lines[-1] = lines[-1][:last_ew] + if to_encode[0] in WSP: + # We're joining this to non-encoded text, so don't encode + # the leading blank. + leading_wsp = to_encode[0] + to_encode = to_encode[1:] + if (len(lines[-1]) == maxlen): + lines.append(_steal_trailing_WSP_if_exists(lines)) + lines[-1] += leading_wsp + trailing_wsp = '' + if to_encode[-1] in WSP: + # Likewise for the trailing space. + trailing_wsp = to_encode[-1] + to_encode = to_encode[:-1] + new_last_ew = len(lines[-1]) if last_ew is None else last_ew + while to_encode: + remaining_space = maxlen - len(lines[-1]) + # The RFC2047 chrome takes up 7 characters plus the length + # of the charset name. + encode_as = 'utf-8' if charset == 'us-ascii' else charset + text_space = remaining_space - len(encode_as) - 7 + if text_space <= 0: + lines.append(' ') + # XXX We'll get an infinite loop here if maxlen is <= 7 + continue + first_part = to_encode[:text_space] + ew = _ew.encode(first_part, charset=encode_as) + excess = len(ew) - remaining_space + if excess > 0: + # encode always chooses the shortest encoding, so this + # is guaranteed to fit at this point. + first_part = first_part[:-excess] + ew = _ew.encode(first_part) + lines[-1] += ew + to_encode = to_encode[len(first_part):] + if to_encode: + lines.append(' ') + new_last_ew = len(lines[-1]) + lines[-1] += trailing_wsp + return new_last_ew if ew_combine_allowed else None + +def _fold_mime_parameters(part, lines, maxlen, encoding): + """Fold TokenList 'part' into the 'lines' list as mime parameters. + + Using the decoded list of parameters and values, format them according to + the RFC rules, including using RFC2231 encoding if the value cannot be + expressed in 'encoding' and/or the paramter+value is too long to fit within + 'maxlen'. + + """ + # Special case for RFC2231 encoding: start from decoded values and use + # RFC2231 encoding iff needed. + # + # Note that the 1 and 2s being added to the length calculations are + # accounting for the possibly-needed spaces and semicolons we'll be adding. + # + for name, value in part.params: + # XXX What if this ';' puts us over maxlen the first time through the + # loop? We should split the header value onto a newline in that case, + # but to do that we need to recognize the need earlier or reparse the + # header, so I'm going to ignore that bug for now. It'll only put us + # one character over. + if not lines[-1].rstrip().endswith(';'): + lines[-1] += ';' + charset = encoding + error_handler = 'strict' + try: + value.encode(encoding) + encoding_required = False + except UnicodeEncodeError: + encoding_required = True + if utils._has_surrogates(value): + charset = 'unknown-8bit' + error_handler = 'surrogateescape' + else: + charset = 'utf-8' + if encoding_required: + encoded_value = urllib.parse.quote( + value, safe='', errors=error_handler) + tstr = "{}*={}''{}".format(name, charset, encoded_value) + else: + tstr = '{}={}'.format(name, quote_string(value)) + if len(lines[-1]) + len(tstr) + 1 < maxlen: + lines[-1] = lines[-1] + ' ' + tstr + continue + elif len(tstr) + 2 <= maxlen: + lines.append(' ' + tstr) + continue + # We need multiple sections. We are allowed to mix encoded and + # non-encoded sections, but we aren't going to. We'll encode them all. + section = 0 + extra_chrome = charset + "''" + while value: + chrome_len = len(name) + len(str(section)) + 3 + len(extra_chrome) + if maxlen <= chrome_len + 3: + # We need room for the leading blank, the trailing semicolon, + # and at least one character of the value. If we don't + # have that, we'd be stuck, so in that case fall back to + # the RFC standard width. + maxlen = 78 + splitpoint = maxchars = maxlen - chrome_len - 2 + while True: + partial = value[:splitpoint] + encoded_value = urllib.parse.quote( + partial, safe='', errors=error_handler) + if len(encoded_value) <= maxchars: + break + splitpoint -= 1 + lines.append(" {}*{}*={}{}".format( + name, section, extra_chrome, encoded_value)) + extra_chrome = '' + section += 1 + value = value[splitpoint:] + if value: + lines[-1] += ';' diff --git a/Lib/email/headerregistry.py b/Lib/email/headerregistry.py index 81fee146dcc..00652049f2f 100644 --- a/Lib/email/headerregistry.py +++ b/Lib/email/headerregistry.py @@ -245,13 +245,16 @@ def fold(self, *, policy): the header name and the ': ' separator. """ - # At some point we need to only put fws here if it was in the source. + # At some point we need to put fws here iif it was in the source. header = parser.Header([ parser.HeaderLabel([ parser.ValueTerminal(self.name, 'header-name'), parser.ValueTerminal(':', 'header-sep')]), - parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')]), - self._parse_tree]) + ]) + if self._parse_tree: + header.append( + parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')])) + header.append(self._parse_tree) return header.fold(policy=policy) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index e0ec87d2080..1667617b9e4 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -14,18 +14,7 @@ def test_EWWhiteSpaceTerminal(self): self.assertEqual(x, ' \t') self.assertEqual(str(x), '') self.assertEqual(x.value, '') - self.assertEqual(x.encoded, ' \t') - - # UnstructuredTokenList - - def test_undecodable_bytes_error_preserved(self): - badstr = b"le pouf c\xaflebre".decode('ascii', 'surrogateescape') - unst = parser.get_unstructured(badstr) - self.assertDefectsEqual(unst.all_defects, [errors.UndecodableBytesDefect]) - parts = list(unst.parts) - self.assertDefectsEqual(parts[0].all_defects, []) - self.assertDefectsEqual(parts[1].all_defects, []) - self.assertDefectsEqual(parts[2].all_defects, [errors.UndecodableBytesDefect]) + self.assertEqual(x.token_type, 'fws') class TestParserMixin: @@ -139,7 +128,6 @@ def test_get_encoded_word_sets_extra_attributes(self): 'first second', [], '') - self.assertEqual(ew.encoded, '=?us-ascii*jive?q?first_second?=') self.assertEqual(ew.charset, 'us-ascii') self.assertEqual(ew.lang, 'jive') @@ -150,7 +138,6 @@ def test_get_encoded_word_lang_default_is_blank(self): 'first second', [], '') - self.assertEqual(ew.encoded, '=?us-ascii?q?first_second?=') self.assertEqual(ew.charset, 'us-ascii') self.assertEqual(ew.lang, '') @@ -2700,28 +2687,37 @@ def test_address_list_with_unicode_names_in_quotes(self): # and with unicode tokens in the comments. Spaces inside the quotes # currently don't do the right thing. - def test_initial_whitespace_splitting(self): + def test_split_at_whitespace_after_header_before_long_token(self): body = parser.get_unstructured(' ' + 'x'*77) header = parser.Header([ parser.HeaderLabel([parser.ValueTerminal('test:', 'atext')]), parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')]), body]) self._test(header, 'test: \n ' + 'x'*77 + '\n') - def test_whitespace_splitting(self): + def test_split_at_whitespace_before_long_token(self): self._test(parser.get_unstructured('xxx ' + 'y'*77), 'xxx \n ' + 'y'*77 + '\n') + def test_overlong_encodeable_is_wrapped(self): + first_token_with_whitespace = 'xxx ' + chrome_leader = '=?utf-8?q?' + len_chrome = len(chrome_leader) + 2 + len_non_y = len_chrome + len(first_token_with_whitespace) + self._test(parser.get_unstructured(first_token_with_whitespace + + 'y'*80), + first_token_with_whitespace + chrome_leader + + 'y'*(78-len_non_y) + '?=\n' + + ' ' + chrome_leader + 'y'*(80-(78-len_non_y)) + '?=\n') + def test_long_filename_attachment(self): - folded = self.policy.fold('Content-Disposition', 'attachment; filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TES.txt"') - self.assertEqual( - 'Content-Disposition: attachment;\n filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TES.txt"\n', - folded - ) - folded = self.policy.fold('Content-Disposition', 'attachment; filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_T.txt"') - self.assertEqual( - 'Content-Disposition: attachment;\n filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_T.txt"\n', - folded - ) + self._test(parser.parse_content_disposition_header( + 'attachment; filename="TEST_TEST_TEST_TEST' + '_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TES.txt"'), + "attachment;\n" + " filename*0*=us-ascii''TEST_TEST_TEST_TEST_TEST_TEST" + "_TEST_TEST_TEST_TEST_TEST;\n" + " filename*1*=_TEST_TES.txt\n", + ) if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py index c4f182903af..c1aeaefab77 100644 --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -27,7 +27,6 @@ def msgmaker(self, msg, policy=None): None """), - # From is wrapped because wrapped it fits in 40. 40: textwrap.dedent("""\ To: whom_it_may_concern at example.com From: @@ -40,11 +39,11 @@ def msgmaker(self, msg, policy=None): None """), - # Neither to nor from fit even if put on a new line, - # so we leave them sticking out on the first line. 20: textwrap.dedent("""\ - To: whom_it_may_concern at example.com - From: nobody_you_want_to_know at example.com + To: + whom_it_may_concern at example.com + From: + nobody_you_want_to_know at example.com Subject: We the willing led by the unknowing are doing @@ -169,6 +168,53 @@ def test_compat32_max_line_length_does_not_fold_when_none(self): g.flatten(msg) self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[0])) + def test_rfc2231_wrapping(self): + # This is pretty much just to make sure we don't have an infinite + # loop; I don't expect anyone to hit this in the field. + msg = self.msgmaker(self.typ(textwrap.dedent("""\ + To: nobody + Content-Disposition: attachment; + filename="afilenamelongenoghtowraphere" + + None + """))) + expected = textwrap.dedent("""\ + To: nobody + Content-Disposition: attachment; + filename*0*=us-ascii''afilename; + filename*1*=longenoghtowraphere + + None + """) + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(max_line_length=33)) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + + def test_rfc2231_wrapping_switches_to_default_len_if_too_narrow(self): + # This is just to make sure we don't have an infinite loop; I don't + # expect anyone to hit this in the field, so I'm not bothering to make + # the result optimal (the encoding isn't needed). + msg = self.msgmaker(self.typ(textwrap.dedent("""\ + To: nobody + Content-Disposition: attachment; + filename="afilenamelongenoghtowraphere" + + None + """))) + expected = textwrap.dedent("""\ + To: nobody + Content-Disposition: + attachment; + filename*0*=us-ascii''afilenamelongenoghtowraphere + + None + """) + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(max_line_length=20)) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + class TestGenerator(TestGeneratorBase, TestEmailBase): diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index af836dc9726..30ce0ba54e4 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -229,14 +229,14 @@ def content_type_as_value(self, defects = args[1] if l>1 else [] decoded = args[2] if l>2 and args[2] is not DITTO else source header = 'Content-Type:' + ' ' if source else '' - folded = args[3] if l>3 else header + source + '\n' + folded = args[3] if l>3 else header + decoded + '\n' h = self.make_header('Content-Type', source) self.assertEqual(h.content_type, content_type) self.assertEqual(h.maintype, maintype) self.assertEqual(h.subtype, subtype) self.assertEqual(h.params, parmdict) with self.assertRaises(TypeError): - h.params['abc'] = 'xyz' # params is read-only. + h.params['abc'] = 'xyz' # make sure params is read-only. self.assertDefectsEqual(h.defects, defects) self.assertEqual(h, decoded) self.assertEqual(h.fold(policy=policy.default), folded) @@ -373,9 +373,10 @@ def content_type_as_value(self, 'text/plain; Charset="utf-8"'), # Since this is pretty much the ur-mimeheader, we'll put all the tests - # that exercise the parameter parsing and formatting here. - # - # XXX: question: is minimal quoting preferred? + # that exercise the parameter parsing and formatting here. Note that + # when we refold we may canonicalize, so things like whitespace, + # quoting, and rfc2231 encoding may change from what was in the input + # header. 'unquoted_param_value': ( 'text/plain; title=foo', @@ -384,7 +385,8 @@ def content_type_as_value(self, 'plain', {'title': 'foo'}, [], - 'text/plain; title="foo"'), + 'text/plain; title="foo"', + ), 'param_value_with_tspecials': ( 'text/plain; title="(bar)foo blue"', @@ -415,7 +417,8 @@ def content_type_as_value(self, 'mixed', {'boundary': 'CPIMSSMTPC06p5f3tG'}, [], - 'Multipart/mixed; boundary="CPIMSSMTPC06p5f3tG"'), + 'Multipart/mixed; boundary="CPIMSSMTPC06p5f3tG"', + ), 'spaces_around_semis': ( ('image/jpeg; name="wibble.JPG" ; x-mac-type="4A504547" ; ' @@ -429,14 +432,31 @@ def content_type_as_value(self, [], ('image/jpeg; name="wibble.JPG"; x-mac-type="4A504547"; ' 'x-mac-creator="474B4F4E"'), - # XXX: it could be that we will eventually prefer to fold starting - # from the decoded value, in which case these spaces and similar - # spaces in other tests will be wrong. - ('Content-Type: image/jpeg; name="wibble.JPG" ; ' - 'x-mac-type="4A504547" ;\n' + ('Content-Type: image/jpeg; name="wibble.JPG";' + ' x-mac-type="4A504547";\n' ' x-mac-creator="474B4F4E"\n'), ), + 'lots_of_mime_params': ( + ('image/jpeg; name="wibble.JPG"; x-mac-type="4A504547"; ' + 'x-mac-creator="474B4F4E"; x-extrastuff="make it longer"'), + 'image/jpeg', + 'image', + 'jpeg', + {'name': 'wibble.JPG', + 'x-mac-type': '4A504547', + 'x-mac-creator': '474B4F4E', + 'x-extrastuff': 'make it longer'}, + [], + ('image/jpeg; name="wibble.JPG"; x-mac-type="4A504547"; ' + 'x-mac-creator="474B4F4E"; x-extrastuff="make it longer"'), + # In this case the whole of the MimeParameters does *not* fit + # one one line, so we break at a lower syntactic level. + ('Content-Type: image/jpeg; name="wibble.JPG";' + ' x-mac-type="4A504547";\n' + ' x-mac-creator="474B4F4E"; x-extrastuff="make it longer"\n'), + ), + 'semis_inside_quotes': ( 'image/jpeg; name="Jim&&Jill"', 'image/jpeg', @@ -460,19 +480,25 @@ def content_type_as_value(self, [], r'image/jpeg; name="Jim \"Bob\" Jill"'), - # XXX: This test works except for the refolding of the header. I'll - # deal with that bug when I deal with the other folding bugs. - #'non_ascii_in_params': ( - # ('foo\xa7/bar; b\xa7r=two; ' - # 'baz=thr\xa7e'.encode('latin-1').decode('us-ascii', - # 'surrogateescape')), - # 'foo\uFFFD/bar', - # 'foo\uFFFD', - # 'bar', - # {'b\uFFFDr': 'two', 'baz': 'thr\uFFFDe'}, - # [errors.UndecodableBytesDefect]*3, - # 'foo?/bar; b?r="two"; baz="thr?e"', - # ), + 'non_ascii_in_params': ( + ('foo\xa7/bar; b\xa7r=two; ' + 'baz=thr\xa7e'.encode('latin-1').decode('us-ascii', + 'surrogateescape')), + 'foo\uFFFD/bar', + 'foo\uFFFD', + 'bar', + {'b\uFFFDr': 'two', 'baz': 'thr\uFFFDe'}, + [errors.UndecodableBytesDefect]*3, + 'foo?/bar; b?r="two"; baz="thr?e"', + # XXX Two bugs here: the mime type is not allowed to be an encoded + # word, and we shouldn't be emitting surrogates in the parameter + # names. But I don't know what the behavior should be here, so I'm + # punting for now. In practice this is unlikely to be encountered + # since headers with binary in them only come from a binary source + # and are almost certain to be re-emitted without refolding. + 'Content-Type: =?unknown-8bit?q?foo=A7?=/bar; b\udca7r="two";\n' + " baz*=unknown-8bit''thr%A7e\n", + ), # RFC 2231 parameter tests. @@ -494,19 +520,20 @@ def content_type_as_value(self, [], r'image/jpeg; bar="baz\"foobar\"baz"'), - # XXX: This test works except for the refolding of the header. I'll - # deal with that bug when I deal with the other folding bugs. - #'non_ascii_rfc2231_value': ( - # ('text/plain; charset=us-ascii; ' - # "title*=us-ascii'en'This%20is%20" - # 'not%20f\xa7n').encode('latin-1').decode('us-ascii', - # 'surrogateescape'), - # 'text/plain', - # 'text', - # 'plain', - # {'charset': 'us-ascii', 'title': 'This is not f\uFFFDn'}, - # [errors.UndecodableBytesDefect], - # 'text/plain; charset="us-ascii"; title="This is not f?n"'), + 'non_ascii_rfc2231_value': ( + ('text/plain; charset=us-ascii; ' + "title*=us-ascii'en'This%20is%20" + 'not%20f\xa7n').encode('latin-1').decode('us-ascii', + 'surrogateescape'), + 'text/plain', + 'text', + 'plain', + {'charset': 'us-ascii', 'title': 'This is not f\uFFFDn'}, + [errors.UndecodableBytesDefect], + 'text/plain; charset="us-ascii"; title="This is not f?n"', + 'Content-Type: text/plain; charset="us-ascii";\n' + " title*=unknown-8bit''This%20is%20not%20f%A7n\n", + ), 'rfc2231_encoded_charset': ( 'text/plain; charset*=ansi-x3.4-1968\'\'us-ascii', @@ -529,8 +556,6 @@ def content_type_as_value(self, {'name': 'This is ***fun*** is it not.pdf'}, [], 'text/plain; name="This is ***fun*** is it not.pdf"', - ('Content-Type: text/plain;\tname*0*=\'\'This%20is%20;\n' - '\tname*1*=%2A%2A%2Afun%2A%2A%2A%20;\tname*2="is it not.pdf"\n'), ), # Make sure we also handle it if there are spurious double quotes. @@ -545,9 +570,6 @@ def content_type_as_value(self, {'name': 'This is even more ***fun*** is it not.pdf'}, [errors.InvalidHeaderDefect]*2, 'text/plain; name="This is even more ***fun*** is it not.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="us-ascii\'\'This%20is%20even%20more%20";\n' - '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it not.pdf"\n'), ), 'rfc2231_single_quote_inside_double_quotes': ( @@ -562,9 +584,8 @@ def content_type_as_value(self, [errors.InvalidHeaderDefect]*2, ('text/plain; charset="us-ascii"; ' 'title="This is really ***fun*** isn\'t it!"'), - ('Content-Type: text/plain; charset=us-ascii;\n' - '\ttitle*0*="us-ascii\'en\'This%20is%20really%20";\n' - '\ttitle*1*="%2A%2A%2Afun%2A%2A%2A%20";\ttitle*2="isn\'t it!"\n'), + ('Content-Type: text/plain; charset="us-ascii";\n' + ' title="This is really ***fun*** isn\'t it!"\n'), ), 'rfc2231_single_quote_in_value_with_charset_and_lang': ( @@ -576,9 +597,6 @@ def content_type_as_value(self, {'name': "Frank's Document"}, [errors.InvalidHeaderDefect]*2, 'application/x-foo; name="Frank\'s Document"', - ('Content-Type: application/x-foo;\t' - 'name*0*="us-ascii\'en-us\'Frank\'s";\n' - ' name*1*=" Document"\n'), ), 'rfc2231_single_quote_in_non_encoded_value': ( @@ -590,9 +608,6 @@ def content_type_as_value(self, {'name': "us-ascii'en-us'Frank's Document"}, [], 'application/x-foo; name="us-ascii\'en-us\'Frank\'s Document"', - ('Content-Type: application/x-foo;\t' - 'name*0="us-ascii\'en-us\'Frank\'s";\n' - ' name*1=" Document"\n'), ), 'rfc2231_no_language_or_charset': ( @@ -615,12 +630,8 @@ def content_type_as_value(self, {'name': 'This is even more ***fun*** is it.pdf'}, [errors.InvalidHeaderDefect]*2, 'text/plain; name="This is even more ***fun*** is it.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="\'\'This%20is%20even%20more%20";\n' - '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'), ), - # XXX: see below...the first name line here should be *0 not *0*. 'rfc2231_partly_encoded': ( ("text/plain;" '\tname*0*="\'\'This%20is%20even%20more%20";' @@ -632,9 +643,6 @@ def content_type_as_value(self, {'name': 'This is even more ***fun*** is it.pdf'}, [errors.InvalidHeaderDefect]*2, 'text/plain; name="This is even more ***fun*** is it.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="\'\'This%20is%20even%20more%20";\n' - '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'), ), 'rfc2231_partly_encoded_2': ( @@ -647,10 +655,11 @@ def content_type_as_value(self, 'plain', {'name': 'This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf'}, [errors.InvalidHeaderDefect], - 'text/plain; name="This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="\'\'This%20is%20even%20more%20";\n' - '\tname*1="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'), + ('text/plain;' + ' name="This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf"'), + ('Content-Type: text/plain;\n' + ' name="This is even more %2A%2A%2Afun%2A%2A%2A%20is' + ' it.pdf"\n'), ), 'rfc2231_unknown_charset_treated_as_ascii': ( @@ -669,9 +678,12 @@ def content_type_as_value(self, 'plain', {'charset': 'utf-8\uFFFD\uFFFD\uFFFD'}, [errors.UndecodableBytesDefect], - 'text/plain; charset="utf-8\uFFFD\uFFFD\uFFFD"'), + 'text/plain; charset="utf-8\uFFFD\uFFFD\uFFFD"', + "Content-Type: text/plain;" + " charset*=unknown-8bit''utf-8%F1%F2%F3\n", + ), - 'rfc2231_utf_8_in_supposedly_ascii_charset_parameter_value': ( + 'rfc2231_utf8_in_supposedly_ascii_charset_parameter_value': ( "text/plain; charset*=ascii''utf-8%E2%80%9D", 'text/plain', 'text', @@ -679,9 +691,11 @@ def content_type_as_value(self, {'charset': 'utf-8?'}, [errors.UndecodableBytesDefect], 'text/plain; charset="utf-8?"', + # XXX Should folding change the charset to utf8? Currently it just + # reproduces the original, which is arguably fine. + "Content-Type: text/plain;" + " charset*=unknown-8bit''utf-8%E2%80%9D\n", ), - # XXX: if the above were *re*folded, it would get tagged as utf-8 - # instead of ascii in the param, since it now contains non-ASCII. 'rfc2231_encoded_then_unencoded_segments': ( ('application/x-foo;' @@ -694,9 +708,6 @@ def content_type_as_value(self, {'name': 'My Document For You'}, [errors.InvalidHeaderDefect], 'application/x-foo; name="My Document For You"', - ('Content-Type: application/x-foo;\t' - 'name*0*="us-ascii\'en-us\'My";\n' - '\tname*1=" Document";\tname*2=" For You"\n'), ), # My reading of the RFC is that this is an invalid header. The RFC @@ -713,11 +724,6 @@ def content_type_as_value(self, {'name': 'My Document For You'}, [errors.InvalidHeaderDefect]*3, 'application/x-foo; name="My Document For You"', - ("Content-Type: application/x-foo;\tname*0=us-ascii'en-us'My;\t" - # XXX: the newline is in the wrong place, come back and fix - # this when the rest of tests pass. - 'name*1*=" Document"\n;' - '\tname*2*=" For You"\n'), ), # XXX: I would say this one should default to ascii/en for the @@ -730,8 +736,7 @@ def content_type_as_value(self, # charset'lang'value pattern exactly *and* there is at least one # encoded segment. Implementing that algorithm will require some # refactoring, so I haven't done it (yet). - - 'rfc2231_qouted_unencoded_then_encoded_segments': ( + 'rfc2231_quoted_unencoded_then_encoded_segments': ( ('application/x-foo;' '\tname*0="us-ascii\'en-us\'My";' '\tname*1*=" Document";' @@ -742,9 +747,25 @@ def content_type_as_value(self, {'name': "us-ascii'en-us'My Document For You"}, [errors.InvalidHeaderDefect]*2, 'application/x-foo; name="us-ascii\'en-us\'My Document For You"', - ('Content-Type: application/x-foo;\t' - 'name*0="us-ascii\'en-us\'My";\n' - '\tname*1*=" Document";\tname*2*=" For You"\n'), + ), + + # Make sure our folding algorithm produces multiple sections correctly. + # We could mix encoded and non-encoded segments, but we don't, we just + # make them all encoded. It might be worth fixing that, since the + # sections can get used for wrapping ascii text. + 'rfc2231_folded_segments_correctly_formatted': ( + ('application/x-foo;' + '\tname="' + "with spaces"*8 + '"'), + 'application/x-foo', + 'application', + 'x-foo', + {'name': "with spaces"*8}, + [], + 'application/x-foo; name="' + "with spaces"*8 + '"', + "Content-Type: application/x-foo;\n" + " name*0*=us-ascii''with%20spaceswith%20spaceswith%20spaceswith" + "%20spaceswith;\n" + " name*1*=%20spaceswith%20spaceswith%20spaceswith%20spaces\n" ), } @@ -827,8 +848,8 @@ def content_disp_as_value(self, [], ('attachment; filename="genome.jpeg"; ' 'modification-date="Wed, 12 Feb 1997 16:29:51 -0500"'), - ('Content-Disposition: attachment; filename=genome.jpeg;\n' - ' modification-date="Wed, 12 Feb 1997 16:29:51 -0500";\n'), + ('Content-Disposition: attachment; filename="genome.jpeg";\n' + ' modification-date="Wed, 12 Feb 1997 16:29:51 -0500"\n'), ), 'no_value': ( @@ -873,7 +894,7 @@ def version_string_as_MIME_Version(self, if source: source = ' ' + source self.assertEqual(h.fold(policy=policy.default), - 'MIME-Version:' + source + '\n') + 'MIME-Version:' + source + '\n') version_string_params = { @@ -1546,15 +1567,39 @@ def test_fold_unstructured_with_overlong_word(self): 'singlewordthatwontfit') self.assertEqual( h.fold(policy=policy.default.clone(max_line_length=20)), - 'Subject: thisisaverylonglineconsistingofasinglewordthatwontfit\n') + 'Subject: \n' + ' =?utf-8?q?thisisa?=\n' + ' =?utf-8?q?verylon?=\n' + ' =?utf-8?q?glineco?=\n' + ' =?utf-8?q?nsistin?=\n' + ' =?utf-8?q?gofasin?=\n' + ' =?utf-8?q?gleword?=\n' + ' =?utf-8?q?thatwon?=\n' + ' =?utf-8?q?tfit?=\n' + ) def test_fold_unstructured_with_two_overlong_words(self): h = self.make_header('Subject', 'thisisaverylonglineconsistingofa' 'singlewordthatwontfit plusanotherverylongwordthatwontfit') self.assertEqual( h.fold(policy=policy.default.clone(max_line_length=20)), - 'Subject: thisisaverylonglineconsistingofasinglewordthatwontfit\n' - ' plusanotherverylongwordthatwontfit\n') + 'Subject: \n' + ' =?utf-8?q?thisisa?=\n' + ' =?utf-8?q?verylon?=\n' + ' =?utf-8?q?glineco?=\n' + ' =?utf-8?q?nsistin?=\n' + ' =?utf-8?q?gofasin?=\n' + ' =?utf-8?q?gleword?=\n' + ' =?utf-8?q?thatwon?=\n' + ' =?utf-8?q?tfit_pl?=\n' + ' =?utf-8?q?usanoth?=\n' + ' =?utf-8?q?erveryl?=\n' + ' =?utf-8?q?ongword?=\n' + ' =?utf-8?q?thatwon?=\n' + ' =?utf-8?q?tfit?=\n' + ) + + # XXX Need test for when max_line_length is less than the chrome size. def test_fold_unstructured_with_slightly_long_word(self): h = self.make_header('Subject', 'thislongwordislessthanmaxlinelen') @@ -1590,6 +1635,18 @@ def test_fold_date_header(self): self.assertEqual(h.fold(policy=policy.default), 'Date: Sat, 02 Feb 2002 17:00:06 -0800\n') + def test_fold_overlong_words_using_RFC2047(self): + h = self.make_header( + 'X-Report-Abuse', + '') + self.assertEqual( + h.fold(policy=policy.default), + 'X-Report-Abuse: =?utf-8?q?=3Chttps=3A//www=2Emailitapp=2E' + 'com/report=5F?=\n' + ' =?utf-8?q?abuse=2Ephp=3Fmid=3Dxxx-xxx-xxxx' + 'xxxxxxxxxxxxxxxxxxxx=3D=3D-xxx-?=\n' + ' =?utf-8?q?xx-xx=3E?=\n') if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst b/Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst new file mode 100644 index 00000000000..c933ee7d916 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst @@ -0,0 +1,3 @@ +The header folding algorithm for the new email policies has been rewritten, +which also fixes bpo-30788, bpo-31831, and bpo-32182. In particular, RFC2231 +folding is now done correctly. From webhook-mailer at python.org Sun Dec 3 19:46:26 2017 From: webhook-mailer at python.org (R. David Murray) Date: Mon, 04 Dec 2017 00:46:26 -0000 Subject: [Python-checkins] bpo-27240 Rewrite the email header folding algorithm. (GH-3488) (#4693) Message-ID: https://github.com/python/cpython/commit/a87ba60fe56ae2ebe80ab9ada6d280a6a1f3d552 commit: a87ba60fe56ae2ebe80ab9ada6d280a6a1f3d552 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: R. David Murray date: 2017-12-03T19:46:23-05:00 summary: bpo-27240 Rewrite the email header folding algorithm. (GH-3488) (#4693) The original algorithm tried to delegate the folding to the tokens so that those tokens whose folding rules differed could specify the differences. However, this resulted in a lot of duplicated code because most of the rules were the same. The new algorithm moves all folding logic into a set of functions external to the token classes, but puts the information about which tokens can be folded in which ways on the tokens...with the exception of mime-parameters, which are a special case (which was not even implemented in the old folder). This algorithm can still probably be improved and hopefully simplified somewhat. Note that some of the test expectations are changed. I believe the changes are toward more desirable and consistent behavior: in general when (re) folding a line the canonical version of the tokens is generated, rather than preserving errors or extra whitespace. (cherry picked from commit 85d5c18c9d83a1d54eecc4c2ad4dce63194107c6) files: A Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst M Lib/email/_header_value_parser.py M Lib/email/headerregistry.py M Lib/test/test_email/test__header_value_parser.py M Lib/test/test_email/test_generator.py M Lib/test/test_email/test_headerregistry.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 9b9697f7734..3ebbbe5383a 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -96,90 +96,6 @@ def quote_string(value): return '"'+str(value).replace('\\', '\\\\').replace('"', r'\"')+'"' -# -# Accumulator for header folding -# - -class _Folded: - - def __init__(self, maxlen, policy): - self.maxlen = maxlen - self.policy = policy - self.lastlen = 0 - self.stickyspace = None - self.firstline = True - self.done = [] - self.current = [] - - def newline(self): - self.done.extend(self.current) - self.done.append(self.policy.linesep) - self.current.clear() - self.lastlen = 0 - - def finalize(self): - if self.current: - self.newline() - - def __str__(self): - return ''.join(self.done) - - def append(self, stoken): - self.current.append(stoken) - - def append_if_fits(self, token, stoken=None): - if stoken is None: - stoken = str(token) - l = len(stoken) - if self.stickyspace is not None: - stickyspace_len = len(self.stickyspace) - if self.lastlen + stickyspace_len + l <= self.maxlen: - self.current.append(self.stickyspace) - self.lastlen += stickyspace_len - self.current.append(stoken) - self.lastlen += l - self.stickyspace = None - self.firstline = False - return True - if token.has_fws: - ws = token.pop_leading_fws() - if ws is not None: - self.stickyspace += str(ws) - stickyspace_len += len(ws) - token._fold(self) - return True - if stickyspace_len and l + 1 <= self.maxlen: - margin = self.maxlen - l - if 0 < margin < stickyspace_len: - trim = stickyspace_len - margin - self.current.append(self.stickyspace[:trim]) - self.stickyspace = self.stickyspace[trim:] - stickyspace_len = trim - self.newline() - self.current.append(self.stickyspace) - self.current.append(stoken) - self.lastlen = l + stickyspace_len - self.stickyspace = None - self.firstline = False - return True - if not self.firstline: - self.newline() - self.current.append(self.stickyspace) - self.current.append(stoken) - self.stickyspace = None - self.firstline = False - return True - if self.lastlen + l <= self.maxlen: - self.current.append(stoken) - self.lastlen += l - return True - if l < self.maxlen: - self.newline() - self.current.append(stoken) - self.lastlen = l - return True - return False - # # TokenList and its subclasses # @@ -187,6 +103,8 @@ def append_if_fits(self, token, stoken=None): class TokenList(list): token_type = None + syntactic_break = True + ew_combine_allowed = True def __init__(self, *args, **kw): super().__init__(*args, **kw) @@ -207,84 +125,13 @@ def value(self): def all_defects(self): return sum((x.all_defects for x in self), self.defects) - # - # Folding API - # - # parts(): - # - # return a list of objects that constitute the "higher level syntactic - # objects" specified by the RFC as the best places to fold a header line. - # The returned objects must include leading folding white space, even if - # this means mutating the underlying parse tree of the object. Each object - # is only responsible for returning *its* parts, and should not drill down - # to any lower level except as required to meet the leading folding white - # space constraint. - # - # _fold(folded): - # - # folded: the result accumulator. This is an instance of _Folded. - # (XXX: I haven't finished factoring this out yet, the folding code - # pretty much uses this as a state object.) When the folded.current - # contains as much text as will fit, the _fold method should call - # folded.newline. - # folded.lastlen: the current length of the test stored in folded.current. - # folded.maxlen: The maximum number of characters that may appear on a - # folded line. Differs from the policy setting in that "no limit" is - # represented by +inf, which means it can be used in the trivially - # logical fashion in comparisons. - # - # Currently no subclasses implement parts, and I think this will remain - # true. A subclass only needs to implement _fold when the generic version - # isn't sufficient. _fold will need to be implemented primarily when it is - # possible for encoded words to appear in the specialized token-list, since - # there is no generic algorithm that can know where exactly the encoded - # words are allowed. A _fold implementation is responsible for filling - # lines in the same general way that the top level _fold does. It may, and - # should, call the _fold method of sub-objects in a similar fashion to that - # of the top level _fold. - # - # XXX: I'm hoping it will be possible to factor the existing code further - # to reduce redundancy and make the logic clearer. - - @property - def parts(self): - klass = self.__class__ - this = [] - for token in self: - if token.startswith_fws(): - if this: - yield this[0] if len(this)==1 else klass(this) - this.clear() - end_ws = token.pop_trailing_ws() - this.append(token) - if end_ws: - yield klass(this) - this = [end_ws] - if this: - yield this[0] if len(this)==1 else klass(this) - def startswith_fws(self): return self[0].startswith_fws() - def pop_leading_fws(self): - if self[0].token_type == 'fws': - return self.pop(0) - return self[0].pop_leading_fws() - - def pop_trailing_ws(self): - if self[-1].token_type == 'cfws': - return self.pop(-1) - return self[-1].pop_trailing_ws() - @property - def has_fws(self): - for part in self: - if part.has_fws: - return True - return False - - def has_leading_comment(self): - return self[0].has_leading_comment() + def as_ew_allowed(self): + """True if all top level tokens of this part may be RFC2047 encoded.""" + return all(part.as_ew_allowed for part in self) @property def comments(self): @@ -294,69 +141,13 @@ def comments(self): return comments def fold(self, *, policy): - # max_line_length 0/None means no limit, ie: infinitely long. - maxlen = policy.max_line_length or float("+inf") - folded = _Folded(maxlen, policy) - self._fold(folded) - folded.finalize() - return str(folded) - - def as_encoded_word(self, charset): - # This works only for things returned by 'parts', which include - # the leading fws, if any, that should be used. - res = [] - ws = self.pop_leading_fws() - if ws: - res.append(ws) - trailer = self.pop(-1) if self[-1].token_type=='fws' else '' - res.append(_ew.encode(str(self), charset)) - res.append(trailer) - return ''.join(res) - - def cte_encode(self, charset, policy): - res = [] - for part in self: - res.append(part.cte_encode(charset, policy)) - 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(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 when utf8 is False. - charset = 'utf-8' - tstr = part.cte_encode(charset, folded.policy) - tlen = len(tstr) - if folded.append_if_fits(part, tstr): - continue - # Peel off the leading whitespace if any and make it sticky, to - # avoid infinite recursion. - ws = part.pop_leading_fws() - if ws is not None: - folded.stickyspace = str(ws) - if folded.append_if_fits(part): - continue - if part.has_fws: - part._fold(folded) - continue - # There are no fold points in this one; it is too long for a single - # line and can't be split...we just have to put it on its own line. - folded.append(tstr) - folded.newline() + return _refold_parse_tree(self, policy=policy) def pprint(self, indent=''): - print('\n'.join(self._pp(indent=''))) + print(self.ppstr(indent=indent)) def ppstr(self, indent=''): - return '\n'.join(self._pp(indent='')) + return '\n'.join(self._pp(indent=indent)) def _pp(self, indent=''): yield '{}{}/{}('.format( @@ -391,173 +182,11 @@ class UnstructuredTokenList(TokenList): token_type = 'unstructured' - 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(encoding) - except UnicodeEncodeError: - if any(isinstance(x, errors.UndecodableBytesDefect) - for x in part.all_defects): - charset = 'unknown-8bit' - else: - charset = 'utf-8' - if last_ew is not None: - # We've already done an EW, combine this one with it - # if there's room. - chunk = get_unstructured( - ''.join(folded.current[last_ew:]+[tstr])).as_encoded_word(charset) - oldlastlen = sum(len(x) for x in folded.current[:last_ew]) - schunk = str(chunk) - lchunk = len(schunk) - if oldlastlen + lchunk <= folded.maxlen: - del folded.current[last_ew:] - folded.append(schunk) - folded.lastlen = oldlastlen + lchunk - continue - tstr = part.as_encoded_word(charset) - is_ew = True - if folded.append_if_fits(part, tstr): - if is_ew: - last_ew = len(folded.current) - 1 - continue - if is_ew or last_ew: - # It's too big to fit on the line, but since we've - # got encoded words we can use encoded word folding. - part._fold_as_ew(folded) - continue - # Peel off the leading whitespace if any and make it sticky, to - # avoid infinite recursion. - ws = part.pop_leading_fws() - if ws is not None: - folded.stickyspace = str(ws) - if folded.append_if_fits(part): - continue - if part.has_fws: - part._fold(folded) - continue - # It can't be split...we just have to put it on its own line. - folded.append(tstr) - folded.newline() - last_ew = None - - def cte_encode(self, charset, policy): - res = [] - last_ew = None - for part in self: - spart = str(part) - try: - spart.encode('us-ascii') - res.append(spart) - except UnicodeEncodeError: - if last_ew is None: - res.append(part.cte_encode(charset, policy)) - last_ew = len(res) - else: - tl = get_unstructured(''.join(res[last_ew:] + [spart])) - res.append(tl.as_encoded_word(charset)) - return ''.join(res) - class Phrase(TokenList): token_type = 'phrase' - def _fold(self, folded): - # As with Unstructured, we can have pure ASCII with or without - # surrogateescape encoded bytes, or we could have unicode. But this - # case is more complicated, since we have to deal with the various - # sub-token types and how they can be composed in the face of - # unicode-that-needs-CTE-encoding, and the fact that if a token a - # 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(encoding) - except UnicodeEncodeError: - if any(isinstance(x, errors.UndecodableBytesDefect) - for x in part.all_defects): - charset = 'unknown-8bit' - else: - charset = 'utf-8' - if last_ew is not None and not part.has_leading_comment(): - # We've already done an EW, let's see if we can combine - # this one with it. The last_ew logic ensures that all we - # have at this point is atoms, no comments or quoted - # strings. So we can treat the text between the last - # encoded word and the content of this token as - # unstructured text, and things will work correctly. But - # we have to strip off any trailing comment on this token - # first, and if it is a quoted string we have to pull out - # the content (we're encoding it, so it no longer needs to - # be quoted). - if part[-1].token_type == 'cfws' and part.comments: - remainder = part.pop(-1) - else: - remainder = '' - for i, token in enumerate(part): - if token.token_type == 'bare-quoted-string': - part[i] = UnstructuredTokenList(token[:]) - chunk = get_unstructured( - ''.join(folded.current[last_ew:]+[tstr])).as_encoded_word(charset) - schunk = str(chunk) - lchunk = len(schunk) - if last_ew + lchunk <= folded.maxlen: - del folded.current[last_ew:] - folded.append(schunk) - folded.lastlen = sum(len(x) for x in folded.current) - continue - tstr = part.as_encoded_word(charset) - tlen = len(tstr) - has_ew = True - if folded.append_if_fits(part, tstr): - if has_ew and not part.comments: - last_ew = len(folded.current) - 1 - elif part.comments or part.token_type == 'quoted-string': - # If a comment is involved we can't combine EWs. And if a - # quoted string is involved, it's not worth the effort to - # try to combine them. - last_ew = None - continue - part._fold(folded) - - def cte_encode(self, charset, policy): - res = [] - last_ew = None - is_ew = False - for part in self: - spart = str(part) - try: - spart.encode('us-ascii') - res.append(spart) - except UnicodeEncodeError: - is_ew = True - if last_ew is None: - if not part.comments: - last_ew = len(res) - res.append(part.cte_encode(charset, policy)) - elif not part.has_leading_comment(): - if part[-1].token_type == 'cfws' and part.comments: - remainder = part.pop(-1) - else: - remainder = '' - for i, token in enumerate(part): - if token.token_type == 'bare-quoted-string': - part[i] = UnstructuredTokenList(token[:]) - tl = get_unstructured(''.join(res[last_ew:] + [spart])) - res[last_ew:] = [tl.as_encoded_word(charset)] - if part.comments or (not is_ew and part.token_type == 'quoted-string'): - last_ew = None - return ''.join(res) - class Word(TokenList): token_type = 'word' @@ -567,9 +196,6 @@ class CFWSList(WhiteSpaceTokenList): token_type = 'cfws' - def has_leading_comment(self): - return bool(self.comments) - class Atom(TokenList): @@ -579,6 +205,7 @@ class Atom(TokenList): class Token(TokenList): token_type = 'token' + encode_as_ew = False class EncodedWord(TokenList): @@ -588,13 +215,6 @@ class EncodedWord(TokenList): charset = None lang = None - @property - def encoded(self): - if self.cte is not None: - return self.cte - _ew.encode(str(self), self.charset) - - class QuotedString(TokenList): @@ -865,6 +485,7 @@ def display_name(self): class Domain(TokenList): token_type = 'domain' + as_ew_allowed = False @property def domain(self): @@ -879,11 +500,13 @@ class DotAtom(TokenList): class DotAtomText(TokenList): token_type = 'dot-atom-text' + as_ew_allowed = True class AddrSpec(TokenList): token_type = 'addr-spec' + as_ew_allowed = False @property def local_part(self): @@ -916,11 +539,13 @@ def addr_spec(self): class ObsLocalPart(TokenList): token_type = 'obs-local-part' + as_ew_allowed = False class DisplayName(Phrase): token_type = 'display-name' + ew_combine_allowed = False @property def display_name(self): @@ -960,6 +585,7 @@ def value(self): class LocalPart(TokenList): token_type = 'local-part' + as_ew_allowed = False @property def value(self): @@ -995,6 +621,7 @@ def local_part(self): class DomainLiteral(TokenList): token_type = 'domain-literal' + as_ew_allowed = False @property def domain(self): @@ -1081,6 +708,7 @@ def stripped_value(self): class MimeParameters(TokenList): token_type = 'mime-parameters' + syntactic_break = False @property def params(self): @@ -1165,6 +793,10 @@ def __str__(self): class ParameterizedHeaderValue(TokenList): + # Set this false so that the value doesn't wind up on a new line even + # if it and the parameters would fit there but not on the first line. + syntactic_break = False + @property def params(self): for token in reversed(self): @@ -1172,18 +804,11 @@ def params(self): return token.params return {} - @property - def parts(self): - if self and self[-1].token_type == 'mime-parameters': - # We don't want to start a new line if all of the params don't fit - # after the value, so unwrap the parameter list. - return TokenList(self[:-1] + self[-1]) - return TokenList(self).parts - class ContentType(ParameterizedHeaderValue): token_type = 'content-type' + as_ew_allowed = False maintype = 'text' subtype = 'plain' @@ -1191,40 +816,27 @@ class ContentType(ParameterizedHeaderValue): class ContentDisposition(ParameterizedHeaderValue): token_type = 'content-disposition' + as_ew_allowed = False content_disposition = None class ContentTransferEncoding(TokenList): token_type = 'content-transfer-encoding' + as_ew_allowed = False cte = '7bit' class HeaderLabel(TokenList): token_type = 'header-label' + as_ew_allowed = False class Header(TokenList): token_type = 'header' - def _fold(self, folded): - folded.append(str(self.pop(0))) - folded.lastlen = len(folded.current[0]) - # The first line of the header is different from all others: we don't - # want to start a new object on a new line if it has any fold points in - # it that would allow part of it to be on the first header line. - # Further, if the first fold point would fit on the new line, we want - # to do that, but if it doesn't we want to put it on the first line. - # Folded supports this via the stickyspace attribute. If this - # attribute is not None, it does the special handling. - folded.stickyspace = str(self.pop(0)) if self[0].token_type == 'cfws' else '' - rest = self.pop(0) - if self: - raise ValueError("Malformed Header token list") - rest._fold(folded) - # # Terminal classes and instances @@ -1232,6 +844,10 @@ def _fold(self, folded): class Terminal(str): + as_ew_allowed = True + ew_combine_allowed = True + syntactic_break = True + def __new__(cls, value, token_type): self = super().__new__(cls, value) self.token_type = token_type @@ -1241,6 +857,9 @@ def __new__(cls, value, token_type): def __repr__(self): return "{}({})".format(self.__class__.__name__, super().__repr__()) + def pprint(self): + print(self.__class__.__name__ + '/' + self.token_type) + @property def all_defects(self): return list(self.defects) @@ -1254,29 +873,14 @@ def _pp(self, indent=''): '' if not self.defects else ' {}'.format(self.defects), )] - def cte_encode(self, charset, policy): - value = str(self) - try: - value.encode('us-ascii') - return value - except UnicodeEncodeError: - return _ew.encode(value, charset) - def pop_trailing_ws(self): # This terminates the recursion. return None - def pop_leading_fws(self): - # This terminates the recursion. - return None - @property def comments(self): return [] - def has_leading_comment(self): - return False - def __getnewargs__(self): return(str(self), self.token_type) @@ -1290,8 +894,6 @@ def value(self): def startswith_fws(self): return True - has_fws = True - class ValueTerminal(Terminal): @@ -1302,11 +904,6 @@ def value(self): def startswith_fws(self): return False - has_fws = False - - def as_encoded_word(self, charset): - return _ew.encode(str(self), charset) - class EWWhiteSpaceTerminal(WhiteSpaceTerminal): @@ -1314,15 +911,9 @@ class EWWhiteSpaceTerminal(WhiteSpaceTerminal): def value(self): return '' - @property - def encoded(self): - return self[:] - def __str__(self): return '' - has_fws = True - # XXX these need to become classes and used as instances so # that a program can't change them in a parse tree and screw @@ -2752,7 +2343,7 @@ def get_parameter(value): if value[0] != "'": raise errors.HeaderParseError("Expected RFC2231 char/lang encoding " "delimiter, but found {!r}".format(value)) - appendto.append(ValueTerminal("'", 'RFC2231 delimiter')) + appendto.append(ValueTerminal("'", 'RFC2231-delimiter')) value = value[1:] if value and value[0] != "'": token, value = get_attrtext(value) @@ -2761,7 +2352,7 @@ def get_parameter(value): if not value or value[0] != "'": raise errors.HeaderParseError("Expected RFC2231 char/lang encoding " "delimiter, but found {}".format(value)) - appendto.append(ValueTerminal("'", 'RFC2231 delimiter')) + appendto.append(ValueTerminal("'", 'RFC2231-delimiter')) value = value[1:] if remainder is not None: # Treat the rest of value as bare quoted string content. @@ -2966,3 +2557,255 @@ def parse_content_transfer_encoding_header(value): token, value = get_phrase(value) cte_header.append(token) return cte_header + + +# +# Header folding +# +# Header folding is complex, with lots of rules and corner cases. The +# following code does its best to obey the rules and handle the corner +# cases, but you can be sure there are few bugs:) +# +# This folder generally canonicalizes as it goes, preferring the stringified +# version of each token. The tokens contain information that supports the +# folder, including which tokens can be encoded in which ways. +# +# Folded text is accumulated in a simple list of strings ('lines'), each +# one of which should be less than policy.max_line_length ('maxlen'). +# + +def _steal_trailing_WSP_if_exists(lines): + wsp = '' + if lines and lines[-1] and lines[-1][-1] in WSP: + wsp = lines[-1][-1] + lines[-1] = lines[-1][:-1] + return wsp + +def _refold_parse_tree(parse_tree, *, policy): + """Return string of contents of parse_tree folded according to RFC rules. + + """ + # max_line_length 0/None means no limit, ie: infinitely long. + maxlen = policy.max_line_length or float("+inf") + encoding = 'utf-8' if policy.utf8 else 'us-ascii' + lines = [''] + last_ew = None + wrap_as_ew_blocked = 0 + want_encoding = False + end_ew_not_allowed = Terminal('', 'wrap_as_ew_blocked') + parts = list(parse_tree) + while parts: + part = parts.pop(0) + if part is end_ew_not_allowed: + wrap_as_ew_blocked -= 1 + continue + tstr = str(part) + try: + tstr.encode(encoding) + charset = encoding + except UnicodeEncodeError: + if any(isinstance(x, errors.UndecodableBytesDefect) + for x in part.all_defects): + charset = 'unknown-8bit' + else: + # If policy.utf8 is false this should really be taken from a + # 'charset' property on the policy. + charset = 'utf-8' + want_encoding = True + if part.token_type == 'mime-parameters': + # Mime parameter folding (using RFC2231) is extra special. + _fold_mime_parameters(part, lines, maxlen, encoding) + continue + if want_encoding and not wrap_as_ew_blocked: + if not part.as_ew_allowed: + want_encoding = False + last_ew = None + if part.syntactic_break: + encoded_part = part.fold(policy=policy)[:-1] # strip nl + if policy.linesep not in encoded_part: + # It fits on a single line + if len(encoded_part) > maxlen - len(lines[-1]): + # But not on this one, so start a new one. + newline = _steal_trailing_WSP_if_exists(lines) + # XXX what if encoded_part has no leading FWS? + lines.append(newline) + lines[-1] += encoded_part + continue + # Either this is not a major syntactic break, so we don't + # want it on a line by itself even if it fits, or it + # doesn't fit on a line by itself. Either way, fall through + # to unpacking the subparts and wrapping them. + if not hasattr(part, 'encode'): + # It's not a Terminal, do each piece individually. + parts = list(part) + parts + else: + # It's a terminal, wrap it as an encoded word, possibly + # combining it with previously encoded words if allowed. + last_ew = _fold_as_ew(tstr, lines, maxlen, last_ew, + part.ew_combine_allowed, charset) + want_encoding = False + continue + if len(tstr) <= maxlen - len(lines[-1]): + lines[-1] += tstr + continue + # This part is too long to fit. The RFC wants us to break at + # "major syntactic breaks", so unless we don't consider this + # to be one, check if it will fit on the next line by itself. + if (part.syntactic_break and + len(tstr) + 1 <= maxlen): + newline = _steal_trailing_WSP_if_exists(lines) + if newline or part.startswith_fws(): + lines.append(newline + tstr) + continue + if not hasattr(part, 'encode'): + # It's not a terminal, try folding the subparts. + newparts = list(part) + if not part.as_ew_allowed: + wrap_as_ew_blocked += 1 + newparts.append(end_ew_not_allowed) + parts = newparts + parts + continue + if part.as_ew_allowed and not wrap_as_ew_blocked: + # It doesn't need CTE encoding, but encode it anyway so we can + # wrap it. + parts.insert(0, part) + want_encoding = True + continue + # We can't figure out how to wrap, it, so give up. + newline = _steal_trailing_WSP_if_exists(lines) + if newline or part.startswith_fws(): + lines.append(newline + tstr) + else: + # We can't fold it onto the next line either... + lines[-1] += tstr + return policy.linesep.join(lines) + policy.linesep + +def _fold_as_ew(to_encode, lines, maxlen, last_ew, ew_combine_allowed, charset): + """Fold string to_encode into lines as encoded word, combining if allowed. + Return the new value for last_ew, or None if ew_combine_allowed is False. + + If there is already an encoded word in the last line of lines (indicated by + a non-None value for last_ew) and ew_combine_allowed is true, decode the + existing ew, combine it with to_encode, and re-encode. Otherwise, encode + to_encode. In either case, split to_encode as necessary so that the + encoded segments fit within maxlen. + + """ + if last_ew is not None and ew_combine_allowed: + to_encode = str( + get_unstructured(lines[-1][last_ew:] + to_encode)) + lines[-1] = lines[-1][:last_ew] + if to_encode[0] in WSP: + # We're joining this to non-encoded text, so don't encode + # the leading blank. + leading_wsp = to_encode[0] + to_encode = to_encode[1:] + if (len(lines[-1]) == maxlen): + lines.append(_steal_trailing_WSP_if_exists(lines)) + lines[-1] += leading_wsp + trailing_wsp = '' + if to_encode[-1] in WSP: + # Likewise for the trailing space. + trailing_wsp = to_encode[-1] + to_encode = to_encode[:-1] + new_last_ew = len(lines[-1]) if last_ew is None else last_ew + while to_encode: + remaining_space = maxlen - len(lines[-1]) + # The RFC2047 chrome takes up 7 characters plus the length + # of the charset name. + encode_as = 'utf-8' if charset == 'us-ascii' else charset + text_space = remaining_space - len(encode_as) - 7 + if text_space <= 0: + lines.append(' ') + # XXX We'll get an infinite loop here if maxlen is <= 7 + continue + first_part = to_encode[:text_space] + ew = _ew.encode(first_part, charset=encode_as) + excess = len(ew) - remaining_space + if excess > 0: + # encode always chooses the shortest encoding, so this + # is guaranteed to fit at this point. + first_part = first_part[:-excess] + ew = _ew.encode(first_part) + lines[-1] += ew + to_encode = to_encode[len(first_part):] + if to_encode: + lines.append(' ') + new_last_ew = len(lines[-1]) + lines[-1] += trailing_wsp + return new_last_ew if ew_combine_allowed else None + +def _fold_mime_parameters(part, lines, maxlen, encoding): + """Fold TokenList 'part' into the 'lines' list as mime parameters. + + Using the decoded list of parameters and values, format them according to + the RFC rules, including using RFC2231 encoding if the value cannot be + expressed in 'encoding' and/or the paramter+value is too long to fit within + 'maxlen'. + + """ + # Special case for RFC2231 encoding: start from decoded values and use + # RFC2231 encoding iff needed. + # + # Note that the 1 and 2s being added to the length calculations are + # accounting for the possibly-needed spaces and semicolons we'll be adding. + # + for name, value in part.params: + # XXX What if this ';' puts us over maxlen the first time through the + # loop? We should split the header value onto a newline in that case, + # but to do that we need to recognize the need earlier or reparse the + # header, so I'm going to ignore that bug for now. It'll only put us + # one character over. + if not lines[-1].rstrip().endswith(';'): + lines[-1] += ';' + charset = encoding + error_handler = 'strict' + try: + value.encode(encoding) + encoding_required = False + except UnicodeEncodeError: + encoding_required = True + if utils._has_surrogates(value): + charset = 'unknown-8bit' + error_handler = 'surrogateescape' + else: + charset = 'utf-8' + if encoding_required: + encoded_value = urllib.parse.quote( + value, safe='', errors=error_handler) + tstr = "{}*={}''{}".format(name, charset, encoded_value) + else: + tstr = '{}={}'.format(name, quote_string(value)) + if len(lines[-1]) + len(tstr) + 1 < maxlen: + lines[-1] = lines[-1] + ' ' + tstr + continue + elif len(tstr) + 2 <= maxlen: + lines.append(' ' + tstr) + continue + # We need multiple sections. We are allowed to mix encoded and + # non-encoded sections, but we aren't going to. We'll encode them all. + section = 0 + extra_chrome = charset + "''" + while value: + chrome_len = len(name) + len(str(section)) + 3 + len(extra_chrome) + if maxlen <= chrome_len + 3: + # We need room for the leading blank, the trailing semicolon, + # and at least one character of the value. If we don't + # have that, we'd be stuck, so in that case fall back to + # the RFC standard width. + maxlen = 78 + splitpoint = maxchars = maxlen - chrome_len - 2 + while True: + partial = value[:splitpoint] + encoded_value = urllib.parse.quote( + partial, safe='', errors=error_handler) + if len(encoded_value) <= maxchars: + break + splitpoint -= 1 + lines.append(" {}*{}*={}{}".format( + name, section, extra_chrome, encoded_value)) + extra_chrome = '' + section += 1 + value = value[splitpoint:] + if value: + lines[-1] += ';' diff --git a/Lib/email/headerregistry.py b/Lib/email/headerregistry.py index 0fc2231e5cb..f5be87f4d24 100644 --- a/Lib/email/headerregistry.py +++ b/Lib/email/headerregistry.py @@ -245,13 +245,16 @@ def fold(self, *, policy): the header name and the ': ' separator. """ - # At some point we need to only put fws here if it was in the source. + # At some point we need to put fws here iif it was in the source. header = parser.Header([ parser.HeaderLabel([ parser.ValueTerminal(self.name, 'header-name'), parser.ValueTerminal(':', 'header-sep')]), - parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')]), - self._parse_tree]) + ]) + if self._parse_tree: + header.append( + parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')])) + header.append(self._parse_tree) return header.fold(policy=policy) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index e0ec87d2080..1667617b9e4 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -14,18 +14,7 @@ def test_EWWhiteSpaceTerminal(self): self.assertEqual(x, ' \t') self.assertEqual(str(x), '') self.assertEqual(x.value, '') - self.assertEqual(x.encoded, ' \t') - - # UnstructuredTokenList - - def test_undecodable_bytes_error_preserved(self): - badstr = b"le pouf c\xaflebre".decode('ascii', 'surrogateescape') - unst = parser.get_unstructured(badstr) - self.assertDefectsEqual(unst.all_defects, [errors.UndecodableBytesDefect]) - parts = list(unst.parts) - self.assertDefectsEqual(parts[0].all_defects, []) - self.assertDefectsEqual(parts[1].all_defects, []) - self.assertDefectsEqual(parts[2].all_defects, [errors.UndecodableBytesDefect]) + self.assertEqual(x.token_type, 'fws') class TestParserMixin: @@ -139,7 +128,6 @@ def test_get_encoded_word_sets_extra_attributes(self): 'first second', [], '') - self.assertEqual(ew.encoded, '=?us-ascii*jive?q?first_second?=') self.assertEqual(ew.charset, 'us-ascii') self.assertEqual(ew.lang, 'jive') @@ -150,7 +138,6 @@ def test_get_encoded_word_lang_default_is_blank(self): 'first second', [], '') - self.assertEqual(ew.encoded, '=?us-ascii?q?first_second?=') self.assertEqual(ew.charset, 'us-ascii') self.assertEqual(ew.lang, '') @@ -2700,28 +2687,37 @@ def test_address_list_with_unicode_names_in_quotes(self): # and with unicode tokens in the comments. Spaces inside the quotes # currently don't do the right thing. - def test_initial_whitespace_splitting(self): + def test_split_at_whitespace_after_header_before_long_token(self): body = parser.get_unstructured(' ' + 'x'*77) header = parser.Header([ parser.HeaderLabel([parser.ValueTerminal('test:', 'atext')]), parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')]), body]) self._test(header, 'test: \n ' + 'x'*77 + '\n') - def test_whitespace_splitting(self): + def test_split_at_whitespace_before_long_token(self): self._test(parser.get_unstructured('xxx ' + 'y'*77), 'xxx \n ' + 'y'*77 + '\n') + def test_overlong_encodeable_is_wrapped(self): + first_token_with_whitespace = 'xxx ' + chrome_leader = '=?utf-8?q?' + len_chrome = len(chrome_leader) + 2 + len_non_y = len_chrome + len(first_token_with_whitespace) + self._test(parser.get_unstructured(first_token_with_whitespace + + 'y'*80), + first_token_with_whitespace + chrome_leader + + 'y'*(78-len_non_y) + '?=\n' + + ' ' + chrome_leader + 'y'*(80-(78-len_non_y)) + '?=\n') + def test_long_filename_attachment(self): - folded = self.policy.fold('Content-Disposition', 'attachment; filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TES.txt"') - self.assertEqual( - 'Content-Disposition: attachment;\n filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TES.txt"\n', - folded - ) - folded = self.policy.fold('Content-Disposition', 'attachment; filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_T.txt"') - self.assertEqual( - 'Content-Disposition: attachment;\n filename="TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_T.txt"\n', - folded - ) + self._test(parser.parse_content_disposition_header( + 'attachment; filename="TEST_TEST_TEST_TEST' + '_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TEST_TES.txt"'), + "attachment;\n" + " filename*0*=us-ascii''TEST_TEST_TEST_TEST_TEST_TEST" + "_TEST_TEST_TEST_TEST_TEST;\n" + " filename*1*=_TEST_TES.txt\n", + ) if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py index c4f182903af..c1aeaefab77 100644 --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -27,7 +27,6 @@ def msgmaker(self, msg, policy=None): None """), - # From is wrapped because wrapped it fits in 40. 40: textwrap.dedent("""\ To: whom_it_may_concern at example.com From: @@ -40,11 +39,11 @@ def msgmaker(self, msg, policy=None): None """), - # Neither to nor from fit even if put on a new line, - # so we leave them sticking out on the first line. 20: textwrap.dedent("""\ - To: whom_it_may_concern at example.com - From: nobody_you_want_to_know at example.com + To: + whom_it_may_concern at example.com + From: + nobody_you_want_to_know at example.com Subject: We the willing led by the unknowing are doing @@ -169,6 +168,53 @@ def test_compat32_max_line_length_does_not_fold_when_none(self): g.flatten(msg) self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[0])) + def test_rfc2231_wrapping(self): + # This is pretty much just to make sure we don't have an infinite + # loop; I don't expect anyone to hit this in the field. + msg = self.msgmaker(self.typ(textwrap.dedent("""\ + To: nobody + Content-Disposition: attachment; + filename="afilenamelongenoghtowraphere" + + None + """))) + expected = textwrap.dedent("""\ + To: nobody + Content-Disposition: attachment; + filename*0*=us-ascii''afilename; + filename*1*=longenoghtowraphere + + None + """) + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(max_line_length=33)) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + + def test_rfc2231_wrapping_switches_to_default_len_if_too_narrow(self): + # This is just to make sure we don't have an infinite loop; I don't + # expect anyone to hit this in the field, so I'm not bothering to make + # the result optimal (the encoding isn't needed). + msg = self.msgmaker(self.typ(textwrap.dedent("""\ + To: nobody + Content-Disposition: attachment; + filename="afilenamelongenoghtowraphere" + + None + """))) + expected = textwrap.dedent("""\ + To: nobody + Content-Disposition: + attachment; + filename*0*=us-ascii''afilenamelongenoghtowraphere + + None + """) + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(max_line_length=20)) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + class TestGenerator(TestGeneratorBase, TestEmailBase): diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index af836dc9726..30ce0ba54e4 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -229,14 +229,14 @@ def content_type_as_value(self, defects = args[1] if l>1 else [] decoded = args[2] if l>2 and args[2] is not DITTO else source header = 'Content-Type:' + ' ' if source else '' - folded = args[3] if l>3 else header + source + '\n' + folded = args[3] if l>3 else header + decoded + '\n' h = self.make_header('Content-Type', source) self.assertEqual(h.content_type, content_type) self.assertEqual(h.maintype, maintype) self.assertEqual(h.subtype, subtype) self.assertEqual(h.params, parmdict) with self.assertRaises(TypeError): - h.params['abc'] = 'xyz' # params is read-only. + h.params['abc'] = 'xyz' # make sure params is read-only. self.assertDefectsEqual(h.defects, defects) self.assertEqual(h, decoded) self.assertEqual(h.fold(policy=policy.default), folded) @@ -373,9 +373,10 @@ def content_type_as_value(self, 'text/plain; Charset="utf-8"'), # Since this is pretty much the ur-mimeheader, we'll put all the tests - # that exercise the parameter parsing and formatting here. - # - # XXX: question: is minimal quoting preferred? + # that exercise the parameter parsing and formatting here. Note that + # when we refold we may canonicalize, so things like whitespace, + # quoting, and rfc2231 encoding may change from what was in the input + # header. 'unquoted_param_value': ( 'text/plain; title=foo', @@ -384,7 +385,8 @@ def content_type_as_value(self, 'plain', {'title': 'foo'}, [], - 'text/plain; title="foo"'), + 'text/plain; title="foo"', + ), 'param_value_with_tspecials': ( 'text/plain; title="(bar)foo blue"', @@ -415,7 +417,8 @@ def content_type_as_value(self, 'mixed', {'boundary': 'CPIMSSMTPC06p5f3tG'}, [], - 'Multipart/mixed; boundary="CPIMSSMTPC06p5f3tG"'), + 'Multipart/mixed; boundary="CPIMSSMTPC06p5f3tG"', + ), 'spaces_around_semis': ( ('image/jpeg; name="wibble.JPG" ; x-mac-type="4A504547" ; ' @@ -429,14 +432,31 @@ def content_type_as_value(self, [], ('image/jpeg; name="wibble.JPG"; x-mac-type="4A504547"; ' 'x-mac-creator="474B4F4E"'), - # XXX: it could be that we will eventually prefer to fold starting - # from the decoded value, in which case these spaces and similar - # spaces in other tests will be wrong. - ('Content-Type: image/jpeg; name="wibble.JPG" ; ' - 'x-mac-type="4A504547" ;\n' + ('Content-Type: image/jpeg; name="wibble.JPG";' + ' x-mac-type="4A504547";\n' ' x-mac-creator="474B4F4E"\n'), ), + 'lots_of_mime_params': ( + ('image/jpeg; name="wibble.JPG"; x-mac-type="4A504547"; ' + 'x-mac-creator="474B4F4E"; x-extrastuff="make it longer"'), + 'image/jpeg', + 'image', + 'jpeg', + {'name': 'wibble.JPG', + 'x-mac-type': '4A504547', + 'x-mac-creator': '474B4F4E', + 'x-extrastuff': 'make it longer'}, + [], + ('image/jpeg; name="wibble.JPG"; x-mac-type="4A504547"; ' + 'x-mac-creator="474B4F4E"; x-extrastuff="make it longer"'), + # In this case the whole of the MimeParameters does *not* fit + # one one line, so we break at a lower syntactic level. + ('Content-Type: image/jpeg; name="wibble.JPG";' + ' x-mac-type="4A504547";\n' + ' x-mac-creator="474B4F4E"; x-extrastuff="make it longer"\n'), + ), + 'semis_inside_quotes': ( 'image/jpeg; name="Jim&&Jill"', 'image/jpeg', @@ -460,19 +480,25 @@ def content_type_as_value(self, [], r'image/jpeg; name="Jim \"Bob\" Jill"'), - # XXX: This test works except for the refolding of the header. I'll - # deal with that bug when I deal with the other folding bugs. - #'non_ascii_in_params': ( - # ('foo\xa7/bar; b\xa7r=two; ' - # 'baz=thr\xa7e'.encode('latin-1').decode('us-ascii', - # 'surrogateescape')), - # 'foo\uFFFD/bar', - # 'foo\uFFFD', - # 'bar', - # {'b\uFFFDr': 'two', 'baz': 'thr\uFFFDe'}, - # [errors.UndecodableBytesDefect]*3, - # 'foo?/bar; b?r="two"; baz="thr?e"', - # ), + 'non_ascii_in_params': ( + ('foo\xa7/bar; b\xa7r=two; ' + 'baz=thr\xa7e'.encode('latin-1').decode('us-ascii', + 'surrogateescape')), + 'foo\uFFFD/bar', + 'foo\uFFFD', + 'bar', + {'b\uFFFDr': 'two', 'baz': 'thr\uFFFDe'}, + [errors.UndecodableBytesDefect]*3, + 'foo?/bar; b?r="two"; baz="thr?e"', + # XXX Two bugs here: the mime type is not allowed to be an encoded + # word, and we shouldn't be emitting surrogates in the parameter + # names. But I don't know what the behavior should be here, so I'm + # punting for now. In practice this is unlikely to be encountered + # since headers with binary in them only come from a binary source + # and are almost certain to be re-emitted without refolding. + 'Content-Type: =?unknown-8bit?q?foo=A7?=/bar; b\udca7r="two";\n' + " baz*=unknown-8bit''thr%A7e\n", + ), # RFC 2231 parameter tests. @@ -494,19 +520,20 @@ def content_type_as_value(self, [], r'image/jpeg; bar="baz\"foobar\"baz"'), - # XXX: This test works except for the refolding of the header. I'll - # deal with that bug when I deal with the other folding bugs. - #'non_ascii_rfc2231_value': ( - # ('text/plain; charset=us-ascii; ' - # "title*=us-ascii'en'This%20is%20" - # 'not%20f\xa7n').encode('latin-1').decode('us-ascii', - # 'surrogateescape'), - # 'text/plain', - # 'text', - # 'plain', - # {'charset': 'us-ascii', 'title': 'This is not f\uFFFDn'}, - # [errors.UndecodableBytesDefect], - # 'text/plain; charset="us-ascii"; title="This is not f?n"'), + 'non_ascii_rfc2231_value': ( + ('text/plain; charset=us-ascii; ' + "title*=us-ascii'en'This%20is%20" + 'not%20f\xa7n').encode('latin-1').decode('us-ascii', + 'surrogateescape'), + 'text/plain', + 'text', + 'plain', + {'charset': 'us-ascii', 'title': 'This is not f\uFFFDn'}, + [errors.UndecodableBytesDefect], + 'text/plain; charset="us-ascii"; title="This is not f?n"', + 'Content-Type: text/plain; charset="us-ascii";\n' + " title*=unknown-8bit''This%20is%20not%20f%A7n\n", + ), 'rfc2231_encoded_charset': ( 'text/plain; charset*=ansi-x3.4-1968\'\'us-ascii', @@ -529,8 +556,6 @@ def content_type_as_value(self, {'name': 'This is ***fun*** is it not.pdf'}, [], 'text/plain; name="This is ***fun*** is it not.pdf"', - ('Content-Type: text/plain;\tname*0*=\'\'This%20is%20;\n' - '\tname*1*=%2A%2A%2Afun%2A%2A%2A%20;\tname*2="is it not.pdf"\n'), ), # Make sure we also handle it if there are spurious double quotes. @@ -545,9 +570,6 @@ def content_type_as_value(self, {'name': 'This is even more ***fun*** is it not.pdf'}, [errors.InvalidHeaderDefect]*2, 'text/plain; name="This is even more ***fun*** is it not.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="us-ascii\'\'This%20is%20even%20more%20";\n' - '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it not.pdf"\n'), ), 'rfc2231_single_quote_inside_double_quotes': ( @@ -562,9 +584,8 @@ def content_type_as_value(self, [errors.InvalidHeaderDefect]*2, ('text/plain; charset="us-ascii"; ' 'title="This is really ***fun*** isn\'t it!"'), - ('Content-Type: text/plain; charset=us-ascii;\n' - '\ttitle*0*="us-ascii\'en\'This%20is%20really%20";\n' - '\ttitle*1*="%2A%2A%2Afun%2A%2A%2A%20";\ttitle*2="isn\'t it!"\n'), + ('Content-Type: text/plain; charset="us-ascii";\n' + ' title="This is really ***fun*** isn\'t it!"\n'), ), 'rfc2231_single_quote_in_value_with_charset_and_lang': ( @@ -576,9 +597,6 @@ def content_type_as_value(self, {'name': "Frank's Document"}, [errors.InvalidHeaderDefect]*2, 'application/x-foo; name="Frank\'s Document"', - ('Content-Type: application/x-foo;\t' - 'name*0*="us-ascii\'en-us\'Frank\'s";\n' - ' name*1*=" Document"\n'), ), 'rfc2231_single_quote_in_non_encoded_value': ( @@ -590,9 +608,6 @@ def content_type_as_value(self, {'name': "us-ascii'en-us'Frank's Document"}, [], 'application/x-foo; name="us-ascii\'en-us\'Frank\'s Document"', - ('Content-Type: application/x-foo;\t' - 'name*0="us-ascii\'en-us\'Frank\'s";\n' - ' name*1=" Document"\n'), ), 'rfc2231_no_language_or_charset': ( @@ -615,12 +630,8 @@ def content_type_as_value(self, {'name': 'This is even more ***fun*** is it.pdf'}, [errors.InvalidHeaderDefect]*2, 'text/plain; name="This is even more ***fun*** is it.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="\'\'This%20is%20even%20more%20";\n' - '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'), ), - # XXX: see below...the first name line here should be *0 not *0*. 'rfc2231_partly_encoded': ( ("text/plain;" '\tname*0*="\'\'This%20is%20even%20more%20";' @@ -632,9 +643,6 @@ def content_type_as_value(self, {'name': 'This is even more ***fun*** is it.pdf'}, [errors.InvalidHeaderDefect]*2, 'text/plain; name="This is even more ***fun*** is it.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="\'\'This%20is%20even%20more%20";\n' - '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'), ), 'rfc2231_partly_encoded_2': ( @@ -647,10 +655,11 @@ def content_type_as_value(self, 'plain', {'name': 'This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf'}, [errors.InvalidHeaderDefect], - 'text/plain; name="This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf"', - ('Content-Type: text/plain;\t' - 'name*0*="\'\'This%20is%20even%20more%20";\n' - '\tname*1="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'), + ('text/plain;' + ' name="This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf"'), + ('Content-Type: text/plain;\n' + ' name="This is even more %2A%2A%2Afun%2A%2A%2A%20is' + ' it.pdf"\n'), ), 'rfc2231_unknown_charset_treated_as_ascii': ( @@ -669,9 +678,12 @@ def content_type_as_value(self, 'plain', {'charset': 'utf-8\uFFFD\uFFFD\uFFFD'}, [errors.UndecodableBytesDefect], - 'text/plain; charset="utf-8\uFFFD\uFFFD\uFFFD"'), + 'text/plain; charset="utf-8\uFFFD\uFFFD\uFFFD"', + "Content-Type: text/plain;" + " charset*=unknown-8bit''utf-8%F1%F2%F3\n", + ), - 'rfc2231_utf_8_in_supposedly_ascii_charset_parameter_value': ( + 'rfc2231_utf8_in_supposedly_ascii_charset_parameter_value': ( "text/plain; charset*=ascii''utf-8%E2%80%9D", 'text/plain', 'text', @@ -679,9 +691,11 @@ def content_type_as_value(self, {'charset': 'utf-8?'}, [errors.UndecodableBytesDefect], 'text/plain; charset="utf-8?"', + # XXX Should folding change the charset to utf8? Currently it just + # reproduces the original, which is arguably fine. + "Content-Type: text/plain;" + " charset*=unknown-8bit''utf-8%E2%80%9D\n", ), - # XXX: if the above were *re*folded, it would get tagged as utf-8 - # instead of ascii in the param, since it now contains non-ASCII. 'rfc2231_encoded_then_unencoded_segments': ( ('application/x-foo;' @@ -694,9 +708,6 @@ def content_type_as_value(self, {'name': 'My Document For You'}, [errors.InvalidHeaderDefect], 'application/x-foo; name="My Document For You"', - ('Content-Type: application/x-foo;\t' - 'name*0*="us-ascii\'en-us\'My";\n' - '\tname*1=" Document";\tname*2=" For You"\n'), ), # My reading of the RFC is that this is an invalid header. The RFC @@ -713,11 +724,6 @@ def content_type_as_value(self, {'name': 'My Document For You'}, [errors.InvalidHeaderDefect]*3, 'application/x-foo; name="My Document For You"', - ("Content-Type: application/x-foo;\tname*0=us-ascii'en-us'My;\t" - # XXX: the newline is in the wrong place, come back and fix - # this when the rest of tests pass. - 'name*1*=" Document"\n;' - '\tname*2*=" For You"\n'), ), # XXX: I would say this one should default to ascii/en for the @@ -730,8 +736,7 @@ def content_type_as_value(self, # charset'lang'value pattern exactly *and* there is at least one # encoded segment. Implementing that algorithm will require some # refactoring, so I haven't done it (yet). - - 'rfc2231_qouted_unencoded_then_encoded_segments': ( + 'rfc2231_quoted_unencoded_then_encoded_segments': ( ('application/x-foo;' '\tname*0="us-ascii\'en-us\'My";' '\tname*1*=" Document";' @@ -742,9 +747,25 @@ def content_type_as_value(self, {'name': "us-ascii'en-us'My Document For You"}, [errors.InvalidHeaderDefect]*2, 'application/x-foo; name="us-ascii\'en-us\'My Document For You"', - ('Content-Type: application/x-foo;\t' - 'name*0="us-ascii\'en-us\'My";\n' - '\tname*1*=" Document";\tname*2*=" For You"\n'), + ), + + # Make sure our folding algorithm produces multiple sections correctly. + # We could mix encoded and non-encoded segments, but we don't, we just + # make them all encoded. It might be worth fixing that, since the + # sections can get used for wrapping ascii text. + 'rfc2231_folded_segments_correctly_formatted': ( + ('application/x-foo;' + '\tname="' + "with spaces"*8 + '"'), + 'application/x-foo', + 'application', + 'x-foo', + {'name': "with spaces"*8}, + [], + 'application/x-foo; name="' + "with spaces"*8 + '"', + "Content-Type: application/x-foo;\n" + " name*0*=us-ascii''with%20spaceswith%20spaceswith%20spaceswith" + "%20spaceswith;\n" + " name*1*=%20spaceswith%20spaceswith%20spaceswith%20spaces\n" ), } @@ -827,8 +848,8 @@ def content_disp_as_value(self, [], ('attachment; filename="genome.jpeg"; ' 'modification-date="Wed, 12 Feb 1997 16:29:51 -0500"'), - ('Content-Disposition: attachment; filename=genome.jpeg;\n' - ' modification-date="Wed, 12 Feb 1997 16:29:51 -0500";\n'), + ('Content-Disposition: attachment; filename="genome.jpeg";\n' + ' modification-date="Wed, 12 Feb 1997 16:29:51 -0500"\n'), ), 'no_value': ( @@ -873,7 +894,7 @@ def version_string_as_MIME_Version(self, if source: source = ' ' + source self.assertEqual(h.fold(policy=policy.default), - 'MIME-Version:' + source + '\n') + 'MIME-Version:' + source + '\n') version_string_params = { @@ -1546,15 +1567,39 @@ def test_fold_unstructured_with_overlong_word(self): 'singlewordthatwontfit') self.assertEqual( h.fold(policy=policy.default.clone(max_line_length=20)), - 'Subject: thisisaverylonglineconsistingofasinglewordthatwontfit\n') + 'Subject: \n' + ' =?utf-8?q?thisisa?=\n' + ' =?utf-8?q?verylon?=\n' + ' =?utf-8?q?glineco?=\n' + ' =?utf-8?q?nsistin?=\n' + ' =?utf-8?q?gofasin?=\n' + ' =?utf-8?q?gleword?=\n' + ' =?utf-8?q?thatwon?=\n' + ' =?utf-8?q?tfit?=\n' + ) def test_fold_unstructured_with_two_overlong_words(self): h = self.make_header('Subject', 'thisisaverylonglineconsistingofa' 'singlewordthatwontfit plusanotherverylongwordthatwontfit') self.assertEqual( h.fold(policy=policy.default.clone(max_line_length=20)), - 'Subject: thisisaverylonglineconsistingofasinglewordthatwontfit\n' - ' plusanotherverylongwordthatwontfit\n') + 'Subject: \n' + ' =?utf-8?q?thisisa?=\n' + ' =?utf-8?q?verylon?=\n' + ' =?utf-8?q?glineco?=\n' + ' =?utf-8?q?nsistin?=\n' + ' =?utf-8?q?gofasin?=\n' + ' =?utf-8?q?gleword?=\n' + ' =?utf-8?q?thatwon?=\n' + ' =?utf-8?q?tfit_pl?=\n' + ' =?utf-8?q?usanoth?=\n' + ' =?utf-8?q?erveryl?=\n' + ' =?utf-8?q?ongword?=\n' + ' =?utf-8?q?thatwon?=\n' + ' =?utf-8?q?tfit?=\n' + ) + + # XXX Need test for when max_line_length is less than the chrome size. def test_fold_unstructured_with_slightly_long_word(self): h = self.make_header('Subject', 'thislongwordislessthanmaxlinelen') @@ -1590,6 +1635,18 @@ def test_fold_date_header(self): self.assertEqual(h.fold(policy=policy.default), 'Date: Sat, 02 Feb 2002 17:00:06 -0800\n') + def test_fold_overlong_words_using_RFC2047(self): + h = self.make_header( + 'X-Report-Abuse', + '') + self.assertEqual( + h.fold(policy=policy.default), + 'X-Report-Abuse: =?utf-8?q?=3Chttps=3A//www=2Emailitapp=2E' + 'com/report=5F?=\n' + ' =?utf-8?q?abuse=2Ephp=3Fmid=3Dxxx-xxx-xxxx' + 'xxxxxxxxxxxxxxxxxxxx=3D=3D-xxx-?=\n' + ' =?utf-8?q?xx-xx=3E?=\n') if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst b/Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst new file mode 100644 index 00000000000..c933ee7d916 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-02-16-06-00.bpo-27240.Kji34M.rst @@ -0,0 +1,3 @@ +The header folding algorithm for the new email policies has been rewritten, +which also fixes bpo-30788, bpo-31831, and bpo-32182. In particular, RFC2231 +folding is now done correctly. From solipsis at pitrou.net Mon Dec 4 04:10:44 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 04 Dec 2017 09:10:44 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20171204091044.90968.6771C2B6DD8F983E@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [-2, 1, 0] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogH7fZPI', '--timeout', '7200'] From webhook-mailer at python.org Mon Dec 4 04:51:59 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 04 Dec 2017 09:51:59 -0000 Subject: [Python-checkins] Fix a regression in uuid added in bpo-32107. (#4677) Message-ID: https://github.com/python/cpython/commit/e69fbb6a560a02d0587b9075afd338a1e9073af0 commit: e69fbb6a560a02d0587b9075afd338a1e9073af0 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-04T11:51:55+02:00 summary: Fix a regression in uuid added in bpo-32107. (#4677) uuid.get_node() always must return a stable result. Also added a test for non-reproducibility of _random_getnode(). Original patch by Xavier de Gaye. files: M Lib/test/test_uuid.py M Lib/uuid.py diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index f113c551209..f21bd6dfa15 100644 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -565,6 +565,9 @@ def test_random_getnode(self): self.assertTrue(node & (1 << 40), '%012x' % node) self.check_node(node) + node2 = self.uuid._random_getnode() + self.assertNotEqual(node2, node, '%012x' % node) + @unittest.skipUnless(os.name == 'posix', 'requires Posix') def test_unix_getnode(self): if not importable('_uuid') and not importable('ctypes'): diff --git a/Lib/uuid.py b/Lib/uuid.py index cb2bc092bdf..be06a6eff3f 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -674,14 +674,14 @@ def getnode(): getters = [_unix_getnode, _ifconfig_getnode, _ip_getnode, _arp_getnode, _lanscan_getnode, _netstat_getnode] - for getter in getters: + for getter in getters + [_random_getnode]: try: _node = getter() except: continue if _node is not None: return _node - return _random_getnode() + assert False, '_random_getnode() returned None' _last_timestamp = None From webhook-mailer at python.org Mon Dec 4 07:29:10 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 04 Dec 2017 12:29:10 -0000 Subject: [Python-checkins] bpo-25054, bpo-1647489: Added support of splitting on zerowidth patterns. (#4471) Message-ID: https://github.com/python/cpython/commit/70d56fb52582d9d3f7c00860d6e90570c6259371 commit: 70d56fb52582d9d3f7c00860d6e90570c6259371 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-04T14:29:05+02:00 summary: bpo-25054, bpo-1647489: Added support of splitting on zerowidth patterns. (#4471) Also fixed searching patterns that could match an empty string. files: A Misc/NEWS.d/next/Library/2017-11-20-01-01-01.bpo-25054.rOlRV6.rst A Misc/NEWS.d/next/Library/2017-11-20-01-29-46.bpo-1647489.-ZNNkh.rst M Doc/library/re.rst M Doc/whatsnew/3.7.rst M Lib/doctest.py M Lib/test/test_re.py M Modules/_sre.c M Modules/sre.h M Modules/sre_lib.h diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 8e6eb30f836..dae1d7ea10a 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -708,37 +708,19 @@ form. That way, separator components are always found at the same relative indices within the result list. - .. note:: - - :func:`split` doesn't currently split a string on an empty pattern match. - For example:: - - >>> re.split('x*', 'axbc') - ['a', 'bc'] + The pattern can match empty strings. :: - Even though ``'x*'`` also matches 0 'x' before 'a', between 'b' and 'c', - and after 'c', currently these matches are ignored. The correct behavior - (i.e. splitting on empty matches too and returning ``['', 'a', 'b', 'c', - '']``) will be implemented in future versions of Python, but since this - is a backward incompatible change, a :exc:`FutureWarning` will be raised - in the meanwhile. - - Patterns that can only match empty strings currently never split the - string. Since this doesn't match the expected behavior, a - :exc:`ValueError` will be raised starting from Python 3.5:: - - >>> re.split("^$", "foo\n\nbar\n", flags=re.M) - Traceback (most recent call last): - File "", line 1, in - ... - ValueError: split() requires a non-empty pattern match. + >>> re.split(r'\b', 'Words, words, words.') + ['', 'Words', ', ', 'words', ', ', 'words', '.'] + >>> re.split(r'(\W*)', '...words...') + ['', '...', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', ''] .. versionchanged:: 3.1 Added the optional flags argument. - .. versionchanged:: 3.5 - Splitting on a pattern that could match an empty string now raises - a warning. Patterns that can only match empty strings are now rejected. + .. versionchanged:: 3.7 + Added support of splitting on a pattern that could match an empty string. + .. function:: findall(pattern, string, flags=0) @@ -746,8 +728,10 @@ form. strings. The *string* is scanned left-to-right, and matches are returned in the order found. If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than - one group. Empty matches are included in the result unless they touch the - beginning of another match. + one group. Empty matches are included in the result. + + .. versionchanged:: 3.7 + Non-empty matches can now start just after a previous empty match. .. function:: finditer(pattern, string, flags=0) @@ -755,8 +739,10 @@ form. Return an :term:`iterator` yielding :ref:`match objects ` over all non-overlapping matches for the RE *pattern* in *string*. The *string* is scanned left-to-right, and matches are returned in the order found. Empty - matches are included in the result unless they touch the beginning of another - match. + matches are included in the result. + + .. versionchanged:: 3.7 + Non-empty matches can now start just after a previous empty match. .. function:: sub(pattern, repl, string, count=0, flags=0) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index b6dad4eab6b..3d23aa773d7 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -364,6 +364,10 @@ The flags :const:`re.ASCII`, :const:`re.LOCALE` and :const:`re.UNICODE` can be set within the scope of a group. (Contributed by Serhiy Storchaka in :issue:`31690`.) +:func:`re.split` now supports splitting on a pattern like ``r'\b'``, +``'^$'`` or ``(?=-)`` that matches an empty string. +(Contributed by Serhiy Storchaka in :issue:`25054`.) + string ------ @@ -768,6 +772,23 @@ Changes in the Python API avoid a warning escape them with a backslash. (Contributed by Serhiy Storchaka in :issue:`30349`.) +* The result of splitting a string on a :mod:`regular expression ` + that could match an empty string has been changed. For example + splitting on ``r'\s*'`` will now split not only on whitespaces as it + did previously, but also between any pair of non-whitespace + characters. The previous behavior can be restored by changing the pattern + to ``r'\s+'``. A :exc:`FutureWarning` was emitted for such patterns since + Python 3.5. + + For patterns that match both empty and non-empty strings, the result of + searching for all matches may also be changed in other cases. For example + in the string ``'a\n\n'``, the pattern ``r'(?m)^\s*?$'`` will not only + match empty strings at positions 2 and 3, but also the string ``'\n'`` at + positions 2--3. To match only blank lines, the pattern should be rewritten + as ``r'(?m)^[^\S\n]*$'``. + + (Contributed by Serhiy Storchaka in :issue:`25054`.) + * :class:`tracemalloc.Traceback` frames are now sorted from oldest to most recent to be more consistent with :mod:`traceback`. (Contributed by Jesse Bakker in :issue:`32121`.) diff --git a/Lib/doctest.py b/Lib/doctest.py index 5e5bc21a038..c1d8a1db111 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1611,7 +1611,7 @@ def check_output(self, want, got, optionflags): '', want) # If a line in got contains only spaces, then remove the # spaces. - got = re.sub(r'(?m)^\s*?$', '', got) + got = re.sub(r'(?m)^[^\S\n]+$', '', got) if got == want: return True diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index ee87446b792..2344d71abf2 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -331,21 +331,21 @@ def test_re_split(self): ['', 'a', '', '', 'c']) for sep, expected in [ - (':*', ['', 'a', 'b', 'c']), - ('(?::*)', ['', 'a', 'b', 'c']), - ('(:*)', ['', ':', 'a', ':', 'b', '::', 'c']), - ('(:)*', ['', ':', 'a', ':', 'b', ':', 'c']), + (':*', ['', 'a', 'b', 'c', '']), + ('(?::*)', ['', 'a', 'b', 'c', '']), + ('(:*)', ['', ':', 'a', ':', 'b', '::', 'c', '', '']), + ('(:)*', ['', ':', 'a', ':', 'b', ':', 'c', None, '']), ]: - with self.subTest(sep=sep), self.assertWarns(FutureWarning): + with self.subTest(sep=sep): self.assertTypedEqual(re.split(sep, ':a:b::c'), expected) for sep, expected in [ - ('', [':a:b::c']), - (r'\b', [':a:b::c']), - (r'(?=:)', [':a:b::c']), - (r'(?<=:)', [':a:b::c']), + ('', ['', ':', 'a', ':', 'b', ':', ':', 'c', '']), + (r'\b', [':', 'a', ':', 'b', '::', 'c', '']), + (r'(?=:)', ['', ':a', ':b', ':', ':c']), + (r'(?<=:)', [':', 'a:', 'b:', ':', 'c']), ]: - with self.subTest(sep=sep), self.assertRaises(ValueError): + with self.subTest(sep=sep): self.assertTypedEqual(re.split(sep, ':a:b::c'), expected) def test_qualified_re_split(self): @@ -356,9 +356,8 @@ def test_qualified_re_split(self): ['', ':', 'a', ':', 'b::c']) self.assertEqual(re.split("(:+)", ":a:b::c", maxsplit=2), ['', ':', 'a', ':', 'b::c']) - with self.assertWarns(FutureWarning): - self.assertEqual(re.split("(:*)", ":a:b::c", maxsplit=2), - ['', ':', 'a', ':', 'b::c']) + self.assertEqual(re.split("(:*)", ":a:b::c", maxsplit=2), + ['', ':', 'a', ':', 'b::c']) def test_re_findall(self): self.assertEqual(re.findall(":+", "abc"), []) @@ -1751,6 +1750,25 @@ def test_match_repr(self): "span=(3, 5), match='bb'>" % (type(second).__module__, type(second).__qualname__)) + def test_zerowidth(self): + # Issues 852532, 1647489, 3262, 25054. + self.assertEqual(re.split(r"\b", "a::bc"), ['', 'a', '::', 'bc', '']) + self.assertEqual(re.split(r"\b|:+", "a::bc"), ['', 'a', '', 'bc', '']) + self.assertEqual(re.split(r"(?isbytes = isbytes; state->charsize = charsize; + state->match_all = 0; + state->must_advance = 0; state->beginning = ptr; @@ -559,14 +561,14 @@ pattern_dealloc(PatternObject* self) } LOCAL(Py_ssize_t) -sre_match(SRE_STATE* state, SRE_CODE* pattern, int match_all) +sre_match(SRE_STATE* state, SRE_CODE* pattern) { if (state->charsize == 1) - return sre_ucs1_match(state, pattern, match_all); + return sre_ucs1_match(state, pattern, 1); if (state->charsize == 2) - return sre_ucs2_match(state, pattern, match_all); + return sre_ucs2_match(state, pattern, 1); assert(state->charsize == 4); - return sre_ucs4_match(state, pattern, match_all); + return sre_ucs4_match(state, pattern, 1); } LOCAL(Py_ssize_t) @@ -606,7 +608,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, TRACE(("|%p|%p|MATCH\n", PatternObject_GetCode(self), state.ptr)); - status = sre_match(&state, PatternObject_GetCode(self), 0); + status = sre_match(&state, PatternObject_GetCode(self)); TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr)); if (PyErr_Occurred()) { @@ -645,7 +647,8 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, TRACE(("|%p|%p|FULLMATCH\n", PatternObject_GetCode(self), state.ptr)); - status = sre_match(&state, PatternObject_GetCode(self), 1); + state.match_all = 1; + status = sre_match(&state, PatternObject_GetCode(self)); TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr)); if (PyErr_Occurred()) { @@ -808,11 +811,8 @@ _sre_SRE_Pattern_findall_impl(PatternObject *self, PyObject *string, if (status < 0) goto error; - if (state.ptr == state.start) - state.start = (void*) ((char*) state.ptr + state.charsize); - else - state.start = state.ptr; - + state.must_advance = (state.ptr == state.start); + state.start = state.ptr; } state_fini(&state); @@ -901,17 +901,6 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, void* last; 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; - } if (!state_init(&state, self, string, 0, PY_SSIZE_T_MAX)) return NULL; @@ -942,14 +931,6 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, goto error; } - if (state.start == state.ptr) { - if (last == state.end || state.ptr == 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), @@ -974,7 +955,7 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, } n = n + 1; - + state.must_advance = 1; last = state.start = state.ptr; } @@ -1101,9 +1082,7 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, 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 */ @@ -1130,16 +1109,8 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, i = e; n = n + 1; - -next: - /* move on */ - if (state.ptr == state.end) - break; - if (state.ptr == state.start) - state.start = (void*) ((char*) state.ptr + state.charsize); - else - state.start = state.ptr; - + state.must_advance = 1; + state.start = state.ptr; } /* get segment following last match */ @@ -2450,7 +2421,7 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) state->ptr = state->start; - status = sre_match(state, PatternObject_GetCode(self->pattern), 0); + status = sre_match(state, PatternObject_GetCode(self->pattern)); if (PyErr_Occurred()) return NULL; @@ -2459,12 +2430,10 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) if (status == 0) state->start = NULL; - else if (state->ptr != state->start) + else { + state->must_advance = (state->ptr == state->start); state->start = state->ptr; - else if (state->ptr != state->end) - state->start = (void*) ((char*) state->ptr + state->charsize); - else - state->start = NULL; + } return match; } @@ -2499,12 +2468,10 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self) if (status == 0) state->start = NULL; - else if (state->ptr != state->start) + else { + state->must_advance = (state->ptr == state->start); state->start = state->ptr; - else if (state->ptr != state->end) - state->start = (void*) ((char*) state->ptr + state->charsize); - else - state->start = NULL; + } return match; } diff --git a/Modules/sre.h b/Modules/sre.h index 585d2841a66..a7284881457 100644 --- a/Modules/sre.h +++ b/Modules/sre.h @@ -67,6 +67,7 @@ typedef struct { void* end; /* end of original string */ /* attributes for the match object */ PyObject* string; + Py_buffer buffer; Py_ssize_t pos, endpos; int isbytes; int charsize; /* character size */ @@ -74,11 +75,12 @@ typedef struct { Py_ssize_t lastindex; Py_ssize_t lastmark; void** mark; + int match_all; + int must_advance; /* dynamically allocated stuff */ char* data_stack; size_t data_stack_size; size_t data_stack_base; - Py_buffer buffer; /* current repeat context */ SRE_REPEAT *repeat; } SRE_STATE; diff --git a/Modules/sre_lib.h b/Modules/sre_lib.h index e13b90e8bc0..44948e21ad9 100644 --- a/Modules/sre_lib.h +++ b/Modules/sre_lib.h @@ -199,7 +199,7 @@ SRE(charset_loc_ignore)(SRE_STATE* state, SRE_CODE* set, SRE_CODE ch) return up != lo && SRE(charset)(state, set, up); } -LOCAL(Py_ssize_t) SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all); +LOCAL(Py_ssize_t) SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int toplevel); LOCAL(Py_ssize_t) SRE(count)(SRE_STATE* state, SRE_CODE* pattern, Py_ssize_t maxcount) @@ -510,12 +510,12 @@ do { \ #define JUMP_ASSERT 12 #define JUMP_ASSERT_NOT 13 -#define DO_JUMPX(jumpvalue, jumplabel, nextpattern, matchall) \ +#define DO_JUMPX(jumpvalue, jumplabel, nextpattern, toplevel_) \ DATA_ALLOC(SRE(match_context), nextctx); \ nextctx->last_ctx_pos = ctx_pos; \ nextctx->jump = jumpvalue; \ nextctx->pattern = nextpattern; \ - nextctx->match_all = matchall; \ + nextctx->toplevel = toplevel_; \ ctx_pos = alloc_pos; \ ctx = nextctx; \ goto entrance; \ @@ -523,7 +523,7 @@ do { \ while (0) /* gcc doesn't like labels at end of scopes */ \ #define DO_JUMP(jumpvalue, jumplabel, nextpattern) \ - DO_JUMPX(jumpvalue, jumplabel, nextpattern, ctx->match_all) + DO_JUMPX(jumpvalue, jumplabel, nextpattern, ctx->toplevel) #define DO_JUMP0(jumpvalue, jumplabel, nextpattern) \ DO_JUMPX(jumpvalue, jumplabel, nextpattern, 0) @@ -540,13 +540,13 @@ typedef struct { SRE_CODE chr; SRE_REPEAT* rep; } u; - int match_all; + int toplevel; } SRE(match_context); /* check if string matches the given pattern. returns <0 for error, 0 for failure, and 1 for success */ LOCAL(Py_ssize_t) -SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all) +SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int toplevel) { SRE_CHAR* end = (SRE_CHAR *)state->end; Py_ssize_t alloc_pos, ctx_pos = -1; @@ -563,7 +563,7 @@ SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all) ctx->last_ctx_pos = -1; ctx->jump = JUMP_NONE; ctx->pattern = pattern; - ctx->match_all = match_all; + ctx->toplevel = toplevel; ctx_pos = alloc_pos; entrance: @@ -636,11 +636,14 @@ SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all) case SRE_OP_SUCCESS: /* end of pattern */ TRACE(("|%p|%p|SUCCESS\n", ctx->pattern, ctx->ptr)); - if (!ctx->match_all || ctx->ptr == state->end) { - state->ptr = ctx->ptr; - RETURN_SUCCESS; + if (ctx->toplevel && + ((state->match_all && ctx->ptr != state->end) || + (state->must_advance && ctx->ptr == state->start))) + { + RETURN_FAILURE; } - RETURN_FAILURE; + state->ptr = ctx->ptr; + RETURN_SUCCESS; case SRE_OP_AT: /* match at given position */ @@ -856,7 +859,9 @@ SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all) RETURN_FAILURE; if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS && - ctx->ptr == state->end) { + ctx->ptr == state->end && + !(ctx->toplevel && state->must_advance && ctx->ptr == state->start)) + { /* tail is empty. we're finished */ state->ptr = ctx->ptr; RETURN_SUCCESS; @@ -941,7 +946,10 @@ SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all) } if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS && - (!match_all || ctx->ptr == state->end)) { + !(ctx->toplevel && + ((state->match_all && ctx->ptr != state->end) || + (state->must_advance && ctx->ptr == state->start)))) + { /* tail is empty. we're finished */ state->ptr = ctx->ptr; RETURN_SUCCESS; @@ -1417,6 +1425,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) return 0; /* literal can't match: doesn't fit in char width */ #endif end = (SRE_CHAR *)state->end; + state->must_advance = 0; while (ptr < end) { while (*ptr != c) { if (++ptr >= end) @@ -1458,6 +1467,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) return 0; i = 1; + state->must_advance = 0; do { if (*ptr == (SRE_CHAR) prefix[i]) { if (++i != prefix_len) { @@ -1487,6 +1497,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) if (charset) { /* pattern starts with a character from a known set */ end = (SRE_CHAR *)state->end; + state->must_advance = 0; for (;;) { while (ptr < end && !SRE(charset)(state, charset, *ptr)) ptr++; @@ -1503,13 +1514,15 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) } else { /* general case */ assert(ptr <= end); - while (1) { + TRACE(("|%p|%p|SEARCH\n", pattern, ptr)); + state->start = state->ptr = ptr; + status = SRE(match)(state, pattern, 1); + state->must_advance = 0; + while (status == 0 && ptr < end) { + ptr++; TRACE(("|%p|%p|SEARCH\n", pattern, ptr)); state->start = state->ptr = ptr; status = SRE(match)(state, pattern, 0); - if (status != 0 || ptr >= end) - break; - ptr++; } } From webhook-mailer at python.org Mon Dec 4 07:39:19 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 04 Dec 2017 12:39:19 -0000 Subject: [Python-checkins] Revert "bpo-32197: Try to fix a compiler error on OS X introduced in bpo-32030. (#4681)" (#4694) Message-ID: https://github.com/python/cpython/commit/31a8393cf6a74c870c3484dd68500619f6232c6d commit: 31a8393cf6a74c870c3484dd68500619f6232c6d branch: master author: Victor Stinner committer: GitHub date: 2017-12-04T13:39:15+01:00 summary: Revert "bpo-32197: Try to fix a compiler error on OS X introduced in bpo-32030. (#4681)" (#4694) * Revert "bpo-32197: Try to fix a compiler error on OS X introduced in bpo-32030. (#4681)" This reverts commit 13badcbc60cdbfae1dba1683fd2fae9d70717143. Re-apply commits: * "bpo-32030: _PyPathConfig_Init() sets home and program_name (#4673)" commit af5a895073c24637c094772b27526b94a12ec897. * "bpo-32030: Fix config_get_program_name() on macOS (#4669)" commit e23c06e2b03452c9aaf0dae52296c85e572f9bcd. * "bpo-32030: Add Python/pathconfig.c (#4668)" commit 0ea395ae964c9cd0f499e2ef0d0030c971201220. * "bpo-32030: Don't call _PyPathConfig_Fini() in Py_FinalizeEx() (#4667)" commit ebac19dad6263141d5db0a2c923efe049dba99d2. * "bpo-32030: Fix Py_GetPath(): init program_name (#4665)" commit 9ac3d8882712c9675c3d2f9f84af6b5729575cde. * Fix compilation error on macOS files: A Python/pathconfig.c M Doc/c-api/init.rst M Include/internal/pystate.h M Include/pylifecycle.h M Include/pystate.h M Makefile.pre.in M Modules/getpath.c M Modules/main.c M PC/getpathp.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/pylifecycle.c diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index a9927aba5e1..a3113a390fd 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -40,7 +40,6 @@ The following functions can be safely called before Python is initialized: * :c:func:`Py_GetCompiler` * :c:func:`Py_GetCopyright` * :c:func:`Py_GetPlatform` - * :c:func:`Py_GetProgramName` * :c:func:`Py_GetVersion` * Utilities: @@ -59,8 +58,8 @@ The following functions can be safely called before Python is initialized: The following functions **should not be called** before :c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`, :c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`, - :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome` and - :c:func:`PyEval_InitThreads`. + :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`, + :c:func:`Py_GetProgramName` and :c:func:`PyEval_InitThreads`. .. _global-conf-vars: diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 50ad2fc83a3..b9334212047 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -48,9 +48,36 @@ typedef struct { #endif /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */ wchar_t *module_search_path; + /* Python program name */ + wchar_t *program_name; + /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */ + wchar_t *home; } _PyPathConfig; -#define _PyPathConfig_INIT {.module_search_path = NULL} +#ifdef MS_WINDOWS +#define _PyPathConfig_INIT \ + {.program_full_path = NULL, \ + .prefix = NULL, \ + .dll_path = NULL, \ + .module_search_path = NULL, \ + .program_name = NULL, \ + .home = NULL} +#else +#define _PyPathConfig_INIT \ + {.program_full_path = NULL, \ + .prefix = NULL, \ + .exec_prefix = NULL, \ + .module_search_path = NULL, \ + .program_name = NULL, \ + .home = NULL} +#endif + +PyAPI_DATA(_PyPathConfig) _Py_path_config; + +PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate( + _PyPathConfig *config, + const _PyMainInterpreterConfig *main_config); +PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); /* Full Python runtime state */ diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index d32c98b6985..fa751692a66 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -105,11 +105,10 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( const _PyMainInterpreterConfig *main_config); -PyAPI_FUNC(void) _PyPathConfig_Fini(void); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS -int _Py_CheckPython3(); +int _Py_CheckPython3(void); #endif /* In their own files */ diff --git a/Include/pystate.h b/Include/pystate.h index 60d001c4926..1d8aab6d83f 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -72,7 +72,8 @@ typedef struct { (_PyMainInterpreterConfig){\ .install_signal_handlers = -1, \ .module_search_path_env = NULL, \ - .home = NULL} + .home = NULL, \ + .program_name = NULL} typedef struct _is { diff --git a/Makefile.pre.in b/Makefile.pre.in index f425a89173a..14f6f8abc54 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -337,8 +337,9 @@ PYTHON_OBJS= \ Python/importdl.o \ Python/marshal.o \ Python/modsupport.o \ - Python/mystrtoul.o \ Python/mysnprintf.o \ + Python/mystrtoul.o \ + Python/pathconfig.o \ Python/peephole.o \ Python/pyarena.o \ Python/pyctype.o \ diff --git a/Modules/getpath.c b/Modules/getpath.c index 9f5e8b3ff5c..fc2b5442ce2 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -117,10 +117,7 @@ extern "C" { typedef struct { wchar_t *path_env; /* PATH environment variable */ - wchar_t *home; /* PYTHONHOME environment variable */ - wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ - wchar_t *program_name; /* Program name */ wchar_t *pythonpath; /* PYTHONPATH define */ wchar_t *prefix; /* PREFIX define */ wchar_t *exec_prefix; /* EXEC_PREFIX define */ @@ -135,7 +132,6 @@ typedef struct { static const wchar_t delimiter[2] = {DELIM, '\0'}; static const wchar_t separator[2] = {SEP, '\0'}; -static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; /* Get file status. Encode the path to the locale encoding. */ @@ -360,14 +356,15 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) bytes long. */ static int -search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix) +search_for_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *prefix) { size_t n; wchar_t *vpath; /* If PYTHONHOME is set, we believe it unconditionally */ - if (calculate->home) { - wcsncpy(prefix, calculate->home, MAXPATHLEN); + if (main_config->home) { + wcsncpy(prefix, main_config->home, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; wchar_t *delim = wcschr(prefix, DELIM); if (delim) { @@ -426,9 +423,10 @@ search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix) static void -calculate_prefix(PyCalculatePath *calculate, wchar_t *prefix) +calculate_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *prefix) { - calculate->prefix_found = search_for_prefix(calculate, prefix); + calculate->prefix_found = search_for_prefix(main_config, calculate, prefix); if (!calculate->prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -470,18 +468,19 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) MAXPATHLEN bytes long. */ static int -search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) +search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *exec_prefix) { size_t n; /* If PYTHONHOME is set, we believe it unconditionally */ - if (calculate->home) { - wchar_t *delim = wcschr(calculate->home, DELIM); + if (main_config->home) { + wchar_t *delim = wcschr(main_config->home, DELIM); if (delim) { wcsncpy(exec_prefix, delim+1, MAXPATHLEN); } else { - wcsncpy(exec_prefix, calculate->home, MAXPATHLEN); + wcsncpy(exec_prefix, main_config->home, MAXPATHLEN); } exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, calculate->lib_python); @@ -552,9 +551,12 @@ search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static void -calculate_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) +calculate_exec_prefix(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, wchar_t *exec_prefix) { - calculate->exec_prefix_found = search_for_exec_prefix(calculate, exec_prefix); + calculate->exec_prefix_found = search_for_exec_prefix(main_config, + calculate, + exec_prefix); if (!calculate->exec_prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -585,7 +587,8 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static _PyInitError -calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) +calculate_program_full_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); @@ -604,8 +607,8 @@ calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) * other way to find a directory to start the search from. If * $PATH isn't exported, you lose. */ - if (wcschr(calculate->program_name, SEP)) { - wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); + if (wcschr(main_config->program_name, SEP)) { + wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -621,11 +624,13 @@ calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { - size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1); - if (r == (size_t)-1 || r > MAXPATHLEN) { - /* Could not convert execpath, or it's too long. */ - program_full_path[0] = '\0'; + size_t len; + wchar_t *path = Py_DecodeLocale(execpath, &len); + if (path == NULL) { + return DECODE_LOCALE_ERR("executable path", len); } + wcsncpy(program_full_path, path, MAXPATHLEN); + PyMem_RawFree(path); } #endif /* __APPLE__ */ else if (calculate->path_env) { @@ -645,7 +650,7 @@ calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_full_path, calculate->program_name); + joinpath(program_full_path, main_config->program_name); if (isxfile(program_full_path)) { break; } @@ -810,14 +815,15 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) static _PyInitError -calculate_module_search_path(PyCalculatePath *calculate, +calculate_module_search_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, _PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; - if (calculate->module_search_path_env != NULL) { - bufsz += wcslen(calculate->module_search_path_env) + 1; + if (main_config->module_search_path_env != NULL) { + bufsz += wcslen(main_config->module_search_path_env) + 1; } wchar_t *defpath = calculate->pythonpath; @@ -851,8 +857,8 @@ calculate_module_search_path(PyCalculatePath *calculate, buf[0] = '\0'; /* Run-time value of $PYTHONPATH goes first */ - if (calculate->module_search_path_env) { - wcscpy(buf, calculate->module_search_path_env); + if (main_config->module_search_path_env) { + wcscpy(buf, main_config->module_search_path_env); wcscat(buf, delimiter); } @@ -903,10 +909,6 @@ static _PyInitError calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) { - calculate->home = main_config->home; - calculate->module_search_path_env = main_config->module_search_path_env; - calculate->program_name = main_config->program_name; - size_t len; char *path = getenv("PATH"); if (path) { @@ -948,9 +950,12 @@ calculate_free(PyCalculatePath *calculate) static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) +calculate_path_impl(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { - _PyInitError err = calculate_program_full_path(calculate, config); + _PyInitError err; + + err = calculate_program_full_path(main_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -964,13 +969,13 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); - calculate_prefix(calculate, prefix); + calculate_prefix(main_config, calculate, prefix); calculate_zip_path(calculate, prefix); wchar_t exec_prefix[MAXPATHLEN+1]; memset(exec_prefix, 0, sizeof(exec_prefix)); - calculate_exec_prefix(calculate, exec_prefix); + calculate_exec_prefix(main_config, calculate, exec_prefix); if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !Py_FrozenFlag) @@ -979,8 +984,8 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) "Consider setting $PYTHONHOME to [:]\n"); } - err = calculate_module_search_path(calculate, prefix, exec_prefix, - config); + err = calculate_module_search_path(main_config, calculate, + prefix, exec_prefix, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1003,33 +1008,10 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) } -static void -pathconfig_clear(_PyPathConfig *config) -{ -#define CLEAR(ATTR) \ - do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ - } while (0) - - CLEAR(config->prefix); - CLEAR(config->exec_prefix); - CLEAR(config->program_full_path); - CLEAR(config->module_search_path); -#undef CLEAR -} - - -/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() - and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, + const _PyMainInterpreterConfig *main_config) { - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return _Py_INIT_OK(); - } - PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); @@ -1038,16 +1020,11 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - _PyPathConfig new_path_config; - memset(&new_path_config, 0, sizeof(new_path_config)); - - err = calculate_path_impl(&calculate, &new_path_config); + err = calculate_path_impl(main_config, &calculate, config); if (_Py_INIT_FAILED(err)) { - pathconfig_clear(&new_path_config); goto done; } - _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: @@ -1055,88 +1032,6 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) return err; } - -static void -pathconfig_global_init(void) -{ - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return; - } - - _PyInitError err; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; - - err = _PyMainInterpreterConfig_ReadEnv(&config); - if (!_Py_INIT_FAILED(err)) { - err = _PyPathConfig_Init(&config); - } - _PyMainInterpreterConfig_Clear(&config); - - if (_Py_INIT_FAILED(err)) { - _Py_FatalInitError(err); - } -} - - -void -_PyPathConfig_Fini(void) -{ - pathconfig_clear(&_Py_path_config); -} - - -/* External interface */ -void -Py_SetPath(const wchar_t *path) -{ - if (path == NULL) { - pathconfig_clear(&_Py_path_config); - return; - } - - _PyPathConfig new_config; - new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); - new_config.exec_prefix = _PyMem_RawWcsdup(L""); - new_config.prefix = _PyMem_RawWcsdup(L""); - new_config.module_search_path = _PyMem_RawWcsdup(path); - - pathconfig_clear(&_Py_path_config); - _Py_path_config = new_config; -} - - -wchar_t * -Py_GetPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.module_search_path; -} - - -wchar_t * -Py_GetPrefix(void) -{ - pathconfig_global_init(); - return _Py_path_config.prefix; -} - - -wchar_t * -Py_GetExecPrefix(void) -{ - pathconfig_global_init(); - return _Py_path_config.exec_prefix; -} - - -wchar_t * -Py_GetProgramFullPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.program_full_path; -} - #ifdef __cplusplus } #endif diff --git a/Modules/main.c b/Modules/main.c index e9d524a1463..4095259b88c 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -412,7 +412,6 @@ typedef struct { /* non-zero if filename, command (-c) or module (-m) is set on the command line */ int run_code; - wchar_t *program_name; /* Error message if a function failed */ _PyInitError err; /* PYTHONWARNINGS env var */ @@ -429,7 +428,6 @@ typedef struct { .config = _PyMainInterpreterConfig_INIT, \ .main_importer_path = NULL, \ .run_code = -1, \ - .program_name = NULL, \ .err = _Py_INIT_OK(), \ .env_warning_options = {0, NULL}} @@ -455,7 +453,6 @@ pymain_free_impl(_PyMain *pymain) pymain_optlist_clear(&pymain->env_warning_options); Py_CLEAR(pymain->main_importer_path); - PyMem_RawFree(pymain->program_name); _PyMainInterpreterConfig_Clear(&pymain->config); @@ -874,14 +871,21 @@ pymain_init_stdio(_PyMain *pymain) /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ - environment variables on macOS if available, use argv[0] by default. - - Return 0 on success. - Set pymain->err and return -1 on error. */ -static int -pymain_get_program_name(_PyMain *pymain) + environment variables on macOS if available. */ +static _PyInitError +config_get_program_name(_PyMainInterpreterConfig *config) { - assert(pymain->program_name == NULL); + assert(config->program_name == NULL); + + /* If Py_SetProgramName() was called, use its value */ + wchar_t *program_name = _Py_path_config.program_name; + if (program_name != NULL) { + config->program_name = _PyMem_RawWcsdup(program_name); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + #ifdef __APPLE__ char *p; /* On MacOS X, when the Python interpreter is embedded in an @@ -894,17 +898,13 @@ pymain_get_program_name(_PyMain *pymain) See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') { - wchar_t* buffer; - size_t len = strlen(p) + 1; - - buffer = PyMem_RawMalloc(len * sizeof(wchar_t)); - if (buffer == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + size_t len; + wchar_t* program_name = Py_DecodeLocale(p, &len); + if (program_name == NULL) { + return DECODE_LOCALE_ERR("PYTHONEXECUTABLE environment " + "variable", (Py_ssize_t)len); } - - mbstowcs(buffer, p, len); - pymain->program_name = buffer; + config->program_name = program_name; } #ifdef WITH_NEXT_FRAMEWORK else { @@ -914,21 +914,30 @@ pymain_get_program_name(_PyMain *pymain) * the argv0 of the stub executable */ size_t len; - wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len); - if (wbuf == NULL) { - SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len); - return -1; + wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len); + if (program_name == NULL) { + return DECODE_LOCALE_ERR("__PYVENV_LAUNCHER__ environment " + "variable", (Py_ssize_t)len); } - pymain->program_name = wbuf; + config->program_name = program_name; } } #endif /* WITH_NEXT_FRAMEWORK */ #endif /* __APPLE__ */ - if (pymain->program_name == NULL) { + return _Py_INIT_OK(); +} + + +/* If config_get_program_name() found no program name: use argv[0] by default. + Return 0 on success. Set pymain->err and return -1 on error. */ +static int +pymain_get_program_name(_PyMain *pymain) +{ + if (pymain->config.program_name == NULL) { /* Use argv[0] by default */ - pymain->program_name = pymain_wstrdup(pymain, pymain->argv[0]); - if (pymain->program_name == NULL) { + pymain->config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); + if (pymain->config.program_name == NULL) { return -1; } } @@ -950,13 +959,6 @@ pymain_init_main_interpreter(_PyMain *pymain) { _PyInitError err; - /* TODO: Print any exceptions raised by these operations */ - err = _PyMainInterpreterConfig_Read(&pymain->config); - if (_Py_INIT_FAILED(err)) { - pymain->err = err; - return -1; - } - err = _Py_InitializeMainInterpreter(&pymain->config); if (_Py_INIT_FAILED(err)) { pymain->err = err; @@ -1414,14 +1416,13 @@ config_init_pythonpath(_PyMainInterpreterConfig *config) static _PyInitError -config_init_pythonhome(_PyMainInterpreterConfig *config) +config_init_home(_PyMainInterpreterConfig *config) { wchar_t *home; - home = Py_GetPythonHome(); + /* If Py_SetPythonHome() was called, use its value */ + home = _Py_path_config.home; if (home) { - /* Py_SetPythonHome() has been called before Py_Main(), - use its value */ config->home = _PyMem_RawWcsdup(home); if (config->home == NULL) { return _Py_INIT_NO_MEMORY(); @@ -1441,7 +1442,7 @@ config_init_pythonhome(_PyMainInterpreterConfig *config) _PyInitError _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) { - _PyInitError err = config_init_pythonhome(config); + _PyInitError err = config_init_home(config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1451,11 +1452,9 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) return err; } - /* FIXME: _PyMainInterpreterConfig_Read() has the same code. Remove it - here? See also pymain_get_program_name() and pymain_parse_envvars(). */ - config->program_name = _PyMem_RawWcsdup(Py_GetProgramName()); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); + err = config_get_program_name(config); + if (_Py_INIT_FAILED(err)) { + return err; } return _Py_INIT_OK(); @@ -1481,25 +1480,17 @@ pymain_parse_envvars(_PyMain *pymain) if (pymain_warnings_envvar(pymain) < 0) { return -1; } - if (pymain_get_program_name(pymain) < 0) { - return -1; - } - core_config->allocator = Py_GETENV("PYTHONMALLOC"); - - /* FIXME: move pymain_get_program_name() code into - _PyMainInterpreterConfig_ReadEnv(). - Problem: _PyMainInterpreterConfig_ReadEnv() doesn't have access - to argv[0]. */ - Py_SetProgramName(pymain->program_name); - /* Don't free program_name here: the argument to Py_SetProgramName - must remain valid until Py_FinalizeEx is called. The string is freed - by pymain_free(). */ _PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config); if (_Py_INIT_FAILED(pymain->err)) { pymain->err = err; return -1; } + if (pymain_get_program_name(pymain) < 0) { + return -1; + } + + core_config->allocator = Py_GETENV("PYTHONMALLOC"); /* -X options */ if (pymain_get_xoption(pymain, L"showrefcount")) { @@ -1555,6 +1546,12 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) return -1; } + _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; + return -1; + } + return 0; } @@ -1671,6 +1668,14 @@ pymain_impl(_PyMain *pymain) other special meaning */ pymain->status = 120; } + + /* _PyPathConfig_Clear() cannot be called in Py_FinalizeEx(). + Py_Initialize() and Py_Finalize() can be called multiple times, but it + must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or + Py_SetPythonHome(), whereas _PyPathConfig_Clear() clear all these + parameters. */ + _PyPathConfig_Clear(&_Py_path_config); + return 0; } diff --git a/PC/getpathp.c b/PC/getpathp.c index ad04b6b6efc..08ed8ccc83f 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -118,7 +118,6 @@ #endif typedef struct { - wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ wchar_t *path_env; /* PATH environment variable */ wchar_t *home; /* PYTHONHOME environment variable */ @@ -126,15 +125,11 @@ typedef struct { wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */ wchar_t *user_path; /* from HKEY_CURRENT_USER */ - wchar_t *program_name; /* Program name */ wchar_t argv0_path[MAXPATHLEN+1]; wchar_t zip_path[MAXPATHLEN+1]; } PyCalculatePath; -static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; - - /* determine if "ch" is a separator character */ static int is_sep(wchar_t ch) @@ -503,7 +498,8 @@ get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) static _PyInitError -get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) +get_program_full_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); @@ -518,12 +514,13 @@ get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) * $PATH isn't exported, you lose. */ #ifdef ALTSEP - if (wcschr(calculate->program_name, SEP) || wcschr(calculate->program_name, ALTSEP)) + if (wcschr(main_config->program_name, SEP) || + wcschr(main_config->program_name, ALTSEP)) #else - if (wcschr(calculate->program_name, SEP)) + if (wcschr(main_config->program_name, SEP)) #endif { - wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); + wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); } else if (calculate->path_env) { wchar_t *path = calculate->path_env; @@ -542,7 +539,7 @@ get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, calculate->program_name); + join(program_full_path, main_config->program_name); if (exists(program_full_path)) { break; } @@ -713,9 +710,6 @@ calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) { calculate->home = main_config->home; - calculate->module_search_path_env = main_config->module_search_path_env; - calculate->program_name = main_config->program_name; - calculate->path_env = _wgetenv(L"PATH"); } @@ -724,12 +718,16 @@ static int get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) { if (config->dll_path[0]) { - if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) { + if (!change_ext(spbuffer, config->dll_path, L"._pth") && + exists(spbuffer)) + { return 1; } } if (config->program_full_path[0]) { - if (!change_ext(spbuffer, config->program_full_path, L"._pth") && exists(spbuffer)) { + if (!change_ext(spbuffer, config->program_full_path, L"._pth") && + exists(spbuffer)) + { return 1; } } @@ -815,7 +813,9 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) static _PyInitError -calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) +calculate_module_search_path(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config, + wchar_t *prefix) { int skiphome = calculate->home==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED @@ -824,8 +824,10 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (calculate->module_search_path_env!=NULL || calculate->home!=NULL || \ - calculate->machine_path!=NULL || calculate->user_path!=NULL); + int skipdefault = (main_config->module_search_path_env != NULL || + calculate->home != NULL || + calculate->machine_path != NULL || + calculate->user_path != NULL); /* We need to construct a path from the following parts. (1) the PYTHONPATH environment variable, if set; @@ -861,8 +863,8 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, bufsz += wcslen(calculate->machine_path) + 1; } bufsz += wcslen(calculate->zip_path) + 1; - if (calculate->module_search_path_env != NULL) { - bufsz += wcslen(calculate->module_search_path_env) + 1; + if (main_config->module_search_path_env != NULL) { + bufsz += wcslen(main_config->module_search_path_env) + 1; } wchar_t *buf, *start_buf; @@ -870,9 +872,9 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, if (buf == NULL) { /* We can't exit, so print a warning and limp along */ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); - if (calculate->module_search_path_env) { + if (main_config->module_search_path_env) { fprintf(stderr, "Using environment $PYTHONPATH.\n"); - config->module_search_path = calculate->module_search_path_env; + config->module_search_path = main_config->module_search_path_env; } else { fprintf(stderr, "Using default static path.\n"); @@ -882,8 +884,9 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, } start_buf = buf; - if (calculate->module_search_path_env) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->module_search_path_env)) { + if (main_config->module_search_path_env) { + if (wcscpy_s(buf, bufsz - (buf - start_buf), + main_config->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -996,8 +999,8 @@ calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +calculate_path_impl(const _PyMainInterpreterConfig *main_config, + PyCalculatePath *calculate, _PyPathConfig *config) { _PyInitError err; @@ -1006,7 +1009,7 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, return err; } - err = get_program_full_path(calculate, config); + err = get_program_full_path(main_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1032,7 +1035,7 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, calculate_home_prefix(calculate, prefix); - err = calculate_module_search_path(calculate, config, prefix); + err = calculate_module_search_path(main_config, calculate, config, prefix); if (_Py_INIT_FAILED(err)) { return err; } @@ -1055,145 +1058,28 @@ calculate_free(PyCalculatePath *calculate) } -static void -pathconfig_clear(_PyPathConfig *config) -{ -#define CLEAR(ATTR) \ - do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ - } while (0) - - CLEAR(config->prefix); - CLEAR(config->program_full_path); - CLEAR(config->dll_path); - CLEAR(config->module_search_path); -#undef CLEAR -} - - -/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() - and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, + const _PyMainInterpreterConfig *main_config) { - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return _Py_INIT_OK(); - } - - _PyInitError err; - PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); calculate_init(&calculate, main_config); - _PyPathConfig new_path_config; - memset(&new_path_config, 0, sizeof(new_path_config)); - - err = calculate_path_impl(&calculate, &new_path_config, main_config); + _PyInitError err = calculate_path_impl(main_config, &calculate, config); if (_Py_INIT_FAILED(err)) { goto done; } - _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: - if (_Py_INIT_FAILED(err)) { - pathconfig_clear(&new_path_config); - } calculate_free(&calculate); return err; } -static void -pathconfig_global_init(void) -{ - if (_Py_path_config.module_search_path) { - /* Already initialized */ - return; - } - - _PyInitError err; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; - - err = _PyMainInterpreterConfig_ReadEnv(&config); - if (!_Py_INIT_FAILED(err)) { - err = _PyPathConfig_Init(&config); - } - _PyMainInterpreterConfig_Clear(&config); - - if (_Py_INIT_FAILED(err)) { - _Py_FatalInitError(err); - } -} - - -void -_PyPathConfig_Fini(void) -{ - pathconfig_clear(&_Py_path_config); -} - - -/* External interface */ - -void -Py_SetPath(const wchar_t *path) -{ - if (_Py_path_config.module_search_path != NULL) { - pathconfig_clear(&_Py_path_config); - } - - if (path == NULL) { - return; - } - - _PyPathConfig new_config; - new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); - new_config.prefix = _PyMem_RawWcsdup(L""); - new_config.dll_path = _PyMem_RawWcsdup(L""); - new_config.module_search_path = _PyMem_RawWcsdup(path); - - pathconfig_clear(&_Py_path_config); - _Py_path_config = new_config; -} - - -wchar_t * -Py_GetPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.module_search_path; -} - - -wchar_t * -Py_GetPrefix(void) -{ - pathconfig_global_init(); - return _Py_path_config.prefix; -} - - -wchar_t * -Py_GetExecPrefix(void) -{ - return Py_GetPrefix(); -} - - -wchar_t * -Py_GetProgramFullPath(void) -{ - pathconfig_global_init(); - return _Py_path_config.program_full_path; -} - - /* Load python3.dll before loading any extension module that might refer to it. That way, we can be sure that always the python3.dll corresponding to this python DLL is loaded, not a python3.dll that might be on the path @@ -1203,7 +1089,7 @@ Py_GetProgramFullPath(void) static int python3_checked = 0; static HANDLE hPython3; int -_Py_CheckPython3() +_Py_CheckPython3(void) { wchar_t py3path[MAXPATHLEN+1]; wchar_t *s; diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 3793cbda882..b430e05b629 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -381,6 +381,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 1d33c6e2cc2..c9aa3da355e 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -896,6 +896,9 @@ Python + + Python + Python diff --git a/Python/pathconfig.c b/Python/pathconfig.c new file mode 100644 index 00000000000..6a03f7dca1b --- /dev/null +++ b/Python/pathconfig.c @@ -0,0 +1,266 @@ +/* Path configuration like module_search_path (sys.path) */ + +#include "Python.h" +#include "osdefs.h" +#include "internal/pystate.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +_PyPathConfig _Py_path_config = _PyPathConfig_INIT; + + +void +_PyPathConfig_Clear(_PyPathConfig *config) +{ + /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator, + since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be + called before Py_Initialize() which can changes the memory allocator. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->prefix); + CLEAR(config->program_full_path); +#ifdef MS_WINDOWS + CLEAR(config->dll_path); +#else + CLEAR(config->exec_prefix); +#endif + CLEAR(config->module_search_path); + CLEAR(config->home); + CLEAR(config->program_name); +#undef CLEAR + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + + +/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() + and Py_GetProgramFullPath() */ +_PyInitError +_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +{ + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return _Py_INIT_OK(); + } + + _PyInitError err; + _PyPathConfig new_config = _PyPathConfig_INIT; + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + /* Calculate program_full_path, prefix, exec_prefix (Unix) + or dll_path (Windows), and module_search_path */ + err = _PyPathConfig_Calculate(&new_config, main_config); + if (_Py_INIT_FAILED(err)) { + _PyPathConfig_Clear(&new_config); + goto done; + } + + /* Copy home and program_name from main_config */ + if (main_config->home != NULL) { + new_config.home = _PyMem_RawWcsdup(main_config->home); + if (new_config.home == NULL) { + err = _Py_INIT_NO_MEMORY(); + goto done; + } + } + else { + new_config.home = NULL; + } + + new_config.program_name = _PyMem_RawWcsdup(main_config->program_name); + if (new_config.program_name == NULL) { + err = _Py_INIT_NO_MEMORY(); + goto done; + } + + _PyPathConfig_Clear(&_Py_path_config); + _Py_path_config = new_config; + + err = _Py_INIT_OK(); + +done: + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + return err; +} + + +static void +pathconfig_global_init(void) +{ + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + + _PyInitError err; + _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + + err = _PyMainInterpreterConfig_ReadEnv(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + err = _PyMainInterpreterConfig_Read(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + err = _PyPathConfig_Init(&config); + if (_Py_INIT_FAILED(err)) { + goto error; + } + + _PyMainInterpreterConfig_Clear(&config); + return; + +error: + _PyMainInterpreterConfig_Clear(&config); + _Py_FatalInitError(err); +} + + +/* External interface */ + +void +Py_SetPath(const wchar_t *path) +{ + if (path == NULL) { + _PyPathConfig_Clear(&_Py_path_config); + return; + } + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + _PyPathConfig new_config; + new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); + new_config.prefix = _PyMem_RawWcsdup(L""); +#ifdef MS_WINDOWS + new_config.dll_path = _PyMem_RawWcsdup(L""); +#else + new_config.exec_prefix = _PyMem_RawWcsdup(L""); +#endif + new_config.module_search_path = _PyMem_RawWcsdup(path); + + /* steal the home and program_name values (to leave them unchanged) */ + new_config.home = _Py_path_config.home; + _Py_path_config.home = NULL; + new_config.program_name = _Py_path_config.program_name; + _Py_path_config.program_name = NULL; + + _PyPathConfig_Clear(&_Py_path_config); + _Py_path_config = new_config; + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + + +void +Py_SetPythonHome(wchar_t *home) +{ + if (home == NULL) { + return; + } + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + PyMem_RawFree(_Py_path_config.home); + _Py_path_config.home = _PyMem_RawWcsdup(home); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + if (_Py_path_config.home == NULL) { + Py_FatalError("Py_SetPythonHome() failed: out of memory"); + } +} + + +void +Py_SetProgramName(wchar_t *program_name) +{ + if (program_name == NULL || program_name[0] == L'\0') { + return; + } + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + PyMem_RawFree(_Py_path_config.program_name); + _Py_path_config.program_name = _PyMem_RawWcsdup(program_name); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + if (_Py_path_config.program_name == NULL) { + Py_FatalError("Py_SetProgramName() failed: out of memory"); + } +} + + +wchar_t * +Py_GetPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.module_search_path; +} + + +wchar_t * +Py_GetPrefix(void) +{ + pathconfig_global_init(); + return _Py_path_config.prefix; +} + + +wchar_t * +Py_GetExecPrefix(void) +{ +#ifdef MS_WINDOWS + return Py_GetPrefix(); +#else + pathconfig_global_init(); + return _Py_path_config.exec_prefix; +#endif +} + + +wchar_t * +Py_GetProgramFullPath(void) +{ + pathconfig_global_init(); + return _Py_path_config.program_full_path; +} + + +wchar_t* +Py_GetPythonHome(void) +{ + pathconfig_global_init(); + return _Py_path_config.home; +} + + +wchar_t * +Py_GetProgramName(void) +{ + pathconfig_global_init(); + return _Py_path_config.program_name; +} + + +#ifdef __cplusplus +} +#endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index f0a49f91fb8..523397f1269 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -804,7 +804,12 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) } if (config->program_name == NULL) { - config->program_name = _PyMem_RawWcsdup(Py_GetProgramName()); +#ifdef MS_WINDOWS + const wchar_t *program_name = L"python"; +#else + const wchar_t *program_name = L"python3"; +#endif + config->program_name = _PyMem_RawWcsdup(program_name); if (config->program_name == NULL) { return _Py_INIT_NO_MEMORY(); } @@ -1273,8 +1278,6 @@ Py_FinalizeEx(void) call_ll_exitfuncs(); - _PyPathConfig_Fini(); - _PyRuntime_Finalize(); return status; } @@ -1491,61 +1494,6 @@ Py_EndInterpreter(PyThreadState *tstate) PyInterpreterState_Delete(interp); } -#ifdef MS_WINDOWS -static wchar_t *progname = L"python"; -#else -static wchar_t *progname = L"python3"; -#endif - -void -Py_SetProgramName(wchar_t *pn) -{ - if (pn && *pn) - progname = pn; -} - -wchar_t * -Py_GetProgramName(void) -{ - return progname; -} - -static wchar_t *default_home = NULL; - -void -Py_SetPythonHome(wchar_t *home) -{ - default_home = home; -} - - -wchar_t* -Py_GetPythonHome(void) -{ - /* Use a static buffer to avoid heap memory allocation failure. - Py_GetPythonHome() doesn't allow to report error, and the caller - doesn't release memory. */ - static wchar_t buffer[MAXPATHLEN+1]; - - if (default_home) { - return default_home; - } - - char *home = Py_GETENV("PYTHONHOME"); - if (!home) { - return NULL; - } - - size_t size = Py_ARRAY_LENGTH(buffer); - size_t r = mbstowcs(buffer, home, size); - if (r == (size_t)-1 || r >= size) { - /* conversion failed or the static buffer is too small */ - return NULL; - } - - return buffer; -} - /* Add the __main__ module */ static _PyInitError From webhook-mailer at python.org Mon Dec 4 14:48:28 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 04 Dec 2017 19:48:28 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt to 2017 Dec 3. (#4701) Message-ID: https://github.com/python/cpython/commit/21255fc3932a60c064f85c0fe68f2840f390ebe4 commit: 21255fc3932a60c064f85c0fe68f2840f390ebe4 branch: master author: Terry Jan Reedy committer: GitHub date: 2017-12-04T14:48:25-05:00 summary: bpo-30928: Update idlelib/NEWS.txt to 2017 Dec 3. (#4701) Patches are in 3.7.0a3 even if this update is not. files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index a7a1e9f61e1..71b7976ab8a 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,22 @@ Released on 2018-06-18? ======================== +bpo-32164: Delete unused file idlelib/tabbedpages.py. +Use of TabbedPageSet in configdialog was replaced by ttk.Notebook. + +bpo-32100: Fix old and new bugs in pathbrowser; improve tests. +Patch mostly by Cheryl Sabella. + +bpo-31860: The font sample in the settings dialog is now editable. +Edits persist while IDLE remains open. +Patch by Serhiy Storchake and Terry Jan Reedy. + +bpo-31858: Restrict shell prompt manipulaton to the shell. +Editor and output windows only see an empty last prompt line. This +simplifies the code and fixes a minor bug when newline is inserted. +Sys.ps1, if present, is read on Shell start-up, but is not set or changed. +Patch by Terry Jan Reedy. + bpo-28603: Fix a TypeError that caused a shell restart when printing a traceback that includes an exception that is unhashable. Patch by Zane Bitter. From webhook-mailer at python.org Mon Dec 4 15:23:22 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 04 Dec 2017 20:23:22 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt to 2017 Dec 3. (GH-4701) (#4702) Message-ID: https://github.com/python/cpython/commit/6e687948b0025a1ab0d0773efe62ce64f0c745fc commit: 6e687948b0025a1ab0d0773efe62ce64f0c745fc branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2017-12-04T15:23:18-05:00 summary: bpo-30928: Update idlelib/NEWS.txt to 2017 Dec 3. (GH-4701) (#4702) Patches are in 3.7.0a3 even if this update is not. (cherry picked from commit 21255fc3932a60c064f85c0fe68f2840f390ebe4) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 7dea7ef147f..6e1f0cc95ca 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,22 @@ Released on 2017-09-25? ======================== +bpo-32164: Delete unused file idlelib/tabbedpages.py. +Use of TabbedPageSet in configdialog was replaced by ttk.Notebook. + +bpo-32100: Fix old and new bugs in pathbrowser; improve tests. +Patch mostly by Cheryl Sabella. + +bpo-31860: The font sample in the settings dialog is now editable. +Edits persist while IDLE remains open. +Patch by Serhiy Storchake and Terry Jan Reedy. + +bpo-31858: Restrict shell prompt manipulaton to the shell. +Editor and output windows only see an empty last prompt line. This +simplifies the code and fixes a minor bug when newline is inserted. +Sys.ps1, if present, is read on Shell start-up, but is not set or changed. +Patch by Terry Jan Reedy. + bpo-28603: Fix a TypeError that caused a shell restart when printing a traceback that includes an exception that is unhashable. Patch by Zane Bitter. From webhook-mailer at python.org Mon Dec 4 16:16:21 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 04 Dec 2017 21:16:21 -0000 Subject: [Python-checkins] bpo-32207: Improve tk event exception tracebacks in IDLE. (#4703) Message-ID: https://github.com/python/cpython/commit/1e2fcac4972530aa2c963d7e4011021df5ba866e commit: 1e2fcac4972530aa2c963d7e4011021df5ba866e branch: master author: Terry Jan Reedy committer: GitHub date: 2017-12-04T16:16:18-05:00 summary: bpo-32207: Improve tk event exception tracebacks in IDLE. (#4703) When tk event handling is driven by IDLE's run loop, a confusing and distracting queue.EMPTY traceback context is no longer added to tk event exception tracebacks. The traceback is now the same as when event handling is driven by user code. Patch based on a suggestion by Serhiy Storchaka. files: A Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst M Lib/idlelib/run.py diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 6440e673bf5..176fe3db743 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -134,13 +134,17 @@ def main(del_exitfunc=False): # exiting but got an extra KBI? Try again! continue try: - seq, request = rpc.request_queue.get(block=True, timeout=0.05) + request = rpc.request_queue.get(block=True, timeout=0.05) except queue.Empty: + request = None + # Issue 32207: calling handle_tk_events here adds spurious + # queue.Empty traceback to event handling exceptions. + if request: + seq, (method, args, kwargs) = request + ret = method(*args, **kwargs) + rpc.response_queue.put((seq, ret)) + else: handle_tk_events() - continue - method, args, kwargs = request - ret = method(*args, **kwargs) - rpc.response_queue.put((seq, ret)) except KeyboardInterrupt: if quitting: exit_now = True diff --git a/Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst b/Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst new file mode 100644 index 00000000000..e521c9b0bbd --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst @@ -0,0 +1,6 @@ +Improve tk event exception tracebacks in IDLE. +When tk event handling is driven by IDLE's run loop, a confusing +and distracting queue.EMPTY traceback context is no longer added +to tk event exception tracebacks. The traceback is now the same +as when event handling is driven by user code. Patch based on a +suggestion by Serhiy Storchaka. From webhook-mailer at python.org Mon Dec 4 16:59:00 2017 From: webhook-mailer at python.org (Eric V. Smith) Date: Mon, 04 Dec 2017 21:59:00 -0000 Subject: [Python-checkins] bpo-32214: Implement PEP 557: Data Classes (#4704) Message-ID: https://github.com/python/cpython/commit/f0db54a0a1823534606ed5ce5a772365ba694c41 commit: f0db54a0a1823534606ed5ce5a772365ba694c41 branch: master author: Eric V. Smith committer: GitHub date: 2017-12-04T16:58:55-05:00 summary: bpo-32214: Implement PEP 557: Data Classes (#4704) files: A Lib/dataclasses.py A Lib/test/test_dataclasses.py A Misc/NEWS.d/next/Library/2017-12-04-15-51-57.bpo-32214.uozdNj.rst diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py new file mode 100644 index 00000000000..7a725dfb520 --- /dev/null +++ b/Lib/dataclasses.py @@ -0,0 +1,776 @@ +import sys +import types +from copy import deepcopy +import collections +import inspect + +__all__ = ['dataclass', + 'field', + 'FrozenInstanceError', + 'InitVar', + + # Helper functions. + 'fields', + 'asdict', + 'astuple', + 'make_dataclass', + 'replace', + ] + +# Raised when an attempt is made to modify a frozen class. +class FrozenInstanceError(AttributeError): pass + +# A sentinel object for default values to signal that a +# default-factory will be used. +# This is given a nice repr() which will appear in the function +# signature of dataclasses' constructors. +class _HAS_DEFAULT_FACTORY_CLASS: + def __repr__(self): + return '' +_HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS() + +# A sentinel object to detect if a parameter is supplied or not. +class _MISSING_FACTORY: + def __repr__(self): + return '' +_MISSING = _MISSING_FACTORY() + +# Since most per-field metadata will be unused, create an empty +# read-only proxy that can be shared among all fields. +_EMPTY_METADATA = types.MappingProxyType({}) + +# Markers for the various kinds of fields and pseudo-fields. +_FIELD = object() # An actual field. +_FIELD_CLASSVAR = object() # Not a field, but a ClassVar. +_FIELD_INITVAR = object() # Not a field, but an InitVar. + +# The name of an attribute on the class where we store the Field +# objects. Also used to check if a class is a Data Class. +_MARKER = '__dataclass_fields__' + +# The name of the function, that if it exists, is called at the end of +# __init__. +_POST_INIT_NAME = '__post_init__' + + +class _InitVarMeta(type): + def __getitem__(self, params): + return self + +class InitVar(metaclass=_InitVarMeta): + pass + + +# Instances of Field are only ever created from within this module, +# and only from the field() function, although Field instances are +# exposed externally as (conceptually) read-only objects. +# name and type are filled in after the fact, not in __init__. They're +# not known at the time this class is instantiated, but it's +# convenient if they're available later. +# When cls._MARKER is filled in with a list of Field objects, the name +# and type fields will have been populated. +class Field: + __slots__ = ('name', + 'type', + 'default', + 'default_factory', + 'repr', + 'hash', + 'init', + 'compare', + 'metadata', + '_field_type', # Private: not to be used by user code. + ) + + def __init__(self, default, default_factory, init, repr, hash, compare, + metadata): + self.name = None + self.type = None + self.default = default + self.default_factory = default_factory + self.init = init + self.repr = repr + self.hash = hash + self.compare = compare + self.metadata = (_EMPTY_METADATA + if metadata is None or len(metadata) == 0 else + types.MappingProxyType(metadata)) + self._field_type = None + + def __repr__(self): + return ('Field(' + f'name={self.name!r},' + f'type={self.type},' + f'default={self.default},' + f'default_factory={self.default_factory},' + f'init={self.init},' + f'repr={self.repr},' + f'hash={self.hash},' + f'compare={self.compare},' + f'metadata={self.metadata}' + ')') + + +# This function is used instead of exposing Field creation directly, +# so that a type checker can be told (via overloads) that this is a +# function whose type depends on its parameters. +def field(*, default=_MISSING, default_factory=_MISSING, init=True, repr=True, + hash=None, compare=True, metadata=None): + """Return an object to identify dataclass fields. + + default is the default value of the field. default_factory is a + 0-argument function called to initialize a field's value. If init + is True, the field will be a parameter to the class's __init__() + function. If repr is True, the field will be included in the + object's repr(). If hash is True, the field will be included in + the object's hash(). If compare is True, the field will be used in + comparison functions. metadata, if specified, must be a mapping + which is stored but not otherwise examined by dataclass. + + It is an error to specify both default and default_factory. + """ + + if default is not _MISSING and default_factory is not _MISSING: + raise ValueError('cannot specify both default and default_factory') + return Field(default, default_factory, init, repr, hash, compare, + metadata) + + +def _tuple_str(obj_name, fields): + # Return a string representing each field of obj_name as a tuple + # member. So, if fields is ['x', 'y'] and obj_name is "self", + # return "(self.x,self.y)". + + # Special case for the 0-tuple. + if len(fields) == 0: + return '()' + # Note the trailing comma, needed if this turns out to be a 1-tuple. + return f'({",".join([f"{obj_name}.{f.name}" for f in fields])},)' + + +def _create_fn(name, args, body, globals=None, locals=None, + return_type=_MISSING): + # Note that we mutate locals when exec() is called. Caller beware! + if locals is None: + locals = {} + return_annotation = '' + if return_type is not _MISSING: + locals['_return_type'] = return_type + return_annotation = '->_return_type' + args = ','.join(args) + body = '\n'.join(f' {b}' for b in body) + + txt = f'def {name}({args}){return_annotation}:\n{body}' + + exec(txt, globals, locals) + return locals[name] + + +def _field_assign(frozen, name, value, self_name): + # If we're a frozen class, then assign to our fields in __init__ + # via object.__setattr__. Otherwise, just use a simple + # assignment. + # self_name is what "self" is called in this function: don't + # hard-code "self", since that might be a field name. + if frozen: + return f'object.__setattr__({self_name},{name!r},{value})' + return f'{self_name}.{name}={value}' + + +def _field_init(f, frozen, globals, self_name): + # Return the text of the line in the body of __init__ that will + # initialize this field. + + default_name = f'_dflt_{f.name}' + if f.default_factory is not _MISSING: + if f.init: + # This field has a default factory. If a parameter is + # given, use it. If not, call the factory. + globals[default_name] = f.default_factory + value = (f'{default_name}() ' + f'if {f.name} is _HAS_DEFAULT_FACTORY ' + f'else {f.name}') + else: + # This is a field that's not in the __init__ params, but + # has a default factory function. It needs to be + # initialized here by calling the factory function, + # because there's no other way to initialize it. + + # For a field initialized with a default=defaultvalue, the + # class dict just has the default value + # (cls.fieldname=defaultvalue). But that won't work for a + # default factory, the factory must be called in __init__ + # and we must assign that to self.fieldname. We can't + # fall back to the class dict's value, both because it's + # not set, and because it might be different per-class + # (which, after all, is why we have a factory function!). + + globals[default_name] = f.default_factory + value = f'{default_name}()' + else: + # No default factory. + if f.init: + if f.default is _MISSING: + # There's no default, just do an assignment. + value = f.name + elif f.default is not _MISSING: + globals[default_name] = f.default + value = f.name + else: + # This field does not need initialization. Signify that to + # the caller by returning None. + return None + + # Only test this now, so that we can create variables for the + # default. However, return None to signify that we're not going + # to actually do the assignment statement for InitVars. + if f._field_type == _FIELD_INITVAR: + return None + + # Now, actually generate the field assignment. + return _field_assign(frozen, f.name, value, self_name) + + +def _init_param(f): + # Return the __init__ parameter string for this field. + # For example, the equivalent of 'x:int=3' (except instead of 'int', + # reference a variable set to int, and instead of '3', reference a + # variable set to 3). + if f.default is _MISSING and f.default_factory is _MISSING: + # There's no default, and no default_factory, just + # output the variable name and type. + default = '' + elif f.default is not _MISSING: + # There's a default, this will be the name that's used to look it up. + default = f'=_dflt_{f.name}' + elif f.default_factory is not _MISSING: + # There's a factory function. Set a marker. + default = '=_HAS_DEFAULT_FACTORY' + return f'{f.name}:_type_{f.name}{default}' + + +def _init_fn(fields, frozen, has_post_init, self_name): + # fields contains both real fields and InitVar pseudo-fields. + + # Make sure we don't have fields without defaults following fields + # with defaults. This actually would be caught when exec-ing the + # function source code, but catching it here gives a better error + # message, and future-proofs us in case we build up the function + # using ast. + seen_default = False + for f in fields: + # Only consider fields in the __init__ call. + if f.init: + if not (f.default is _MISSING and f.default_factory is _MISSING): + seen_default = True + elif seen_default: + raise TypeError(f'non-default argument {f.name!r} ' + 'follows default argument') + + globals = {'_MISSING': _MISSING, + '_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY} + + body_lines = [] + for f in fields: + # Do not initialize the pseudo-fields, only the real ones. + line = _field_init(f, frozen, globals, self_name) + if line is not None: + # line is None means that this field doesn't require + # initialization. Just skip it. + body_lines.append(line) + + # Does this class have a post-init function? + if has_post_init: + params_str = ','.join(f.name for f in fields + if f._field_type is _FIELD_INITVAR) + body_lines += [f'{self_name}.{_POST_INIT_NAME}({params_str})'] + + # If no body lines, use 'pass'. + if len(body_lines) == 0: + body_lines = ['pass'] + + locals = {f'_type_{f.name}': f.type for f in fields} + return _create_fn('__init__', + [self_name] +[_init_param(f) for f in fields if f.init], + body_lines, + locals=locals, + globals=globals, + return_type=None) + + +def _repr_fn(fields): + return _create_fn('__repr__', + ['self'], + ['return self.__class__.__qualname__ + f"(' + + ', '.join([f"{f.name}={{self.{f.name}!r}}" + for f in fields]) + + ')"']) + + +def _frozen_setattr(self, name, value): + raise FrozenInstanceError(f'cannot assign to field {name!r}') + + +def _frozen_delattr(self, name): + raise FrozenInstanceError(f'cannot delete field {name!r}') + + +def _cmp_fn(name, op, self_tuple, other_tuple): + # Create a comparison function. If the fields in the object are + # named 'x' and 'y', then self_tuple is the string + # '(self.x,self.y)' and other_tuple is the string + # '(other.x,other.y)'. + + return _create_fn(name, + ['self', 'other'], + [ 'if other.__class__ is self.__class__:', + f' return {self_tuple}{op}{other_tuple}', + 'return NotImplemented']) + + +def _set_eq_fns(cls, fields): + # Create and set the equality comparison methods on cls. + # Pre-compute self_tuple and other_tuple, then re-use them for + # each function. + self_tuple = _tuple_str('self', fields) + other_tuple = _tuple_str('other', fields) + for name, op in [('__eq__', '=='), + ('__ne__', '!='), + ]: + _set_attribute(cls, name, _cmp_fn(name, op, self_tuple, other_tuple)) + + +def _set_order_fns(cls, fields): + # Create and set the ordering methods on cls. + # Pre-compute self_tuple and other_tuple, then re-use them for + # each function. + self_tuple = _tuple_str('self', fields) + other_tuple = _tuple_str('other', fields) + for name, op in [('__lt__', '<'), + ('__le__', '<='), + ('__gt__', '>'), + ('__ge__', '>='), + ]: + _set_attribute(cls, name, _cmp_fn(name, op, self_tuple, other_tuple)) + + +def _hash_fn(fields): + self_tuple = _tuple_str('self', fields) + return _create_fn('__hash__', + ['self'], + [f'return hash({self_tuple})']) + + +def _get_field(cls, a_name, a_type): + # Return a Field object, for this field name and type. ClassVars + # and InitVars are also returned, but marked as such (see + # f._field_type). + + # If the default value isn't derived from field, then it's + # only a normal default value. Convert it to a Field(). + default = getattr(cls, a_name, _MISSING) + if isinstance(default, Field): + f = default + else: + f = field(default=default) + + # Assume it's a normal field until proven otherwise. + f._field_type = _FIELD + + # Only at this point do we know the name and the type. Set them. + f.name = a_name + f.type = a_type + + # If typing has not been imported, then it's impossible for + # any annotation to be a ClassVar. So, only look for ClassVar + # if typing has been imported. + typing = sys.modules.get('typing') + if typing is not None: + # This test uses a typing internal class, but it's the best + # way to test if this is a ClassVar. + if type(a_type) is typing._ClassVar: + # This field is a ClassVar, so it's not a field. + f._field_type = _FIELD_CLASSVAR + + if f._field_type is _FIELD: + # Check if this is an InitVar. + if a_type is InitVar: + # InitVars are not fields, either. + f._field_type = _FIELD_INITVAR + + # Validations for fields. This is delayed until now, instead of + # in the Field() constructor, since only here do we know the field + # name, which allows better error reporting. + + # Special restrictions for ClassVar and InitVar. + if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR): + if f.default_factory is not _MISSING: + raise TypeError(f'field {f.name} cannot have a ' + 'default factory') + # Should I check for other field settings? default_factory + # seems the most serious to check for. Maybe add others. For + # example, how about init=False (or really, + # init=)? It makes no sense for + # ClassVar and InitVar to specify init=. + + # For real fields, disallow mutable defaults for known types. + if f._field_type is _FIELD and isinstance(f.default, (list, dict, set)): + raise ValueError(f'mutable default {type(f.default)} for field ' + f'{f.name} is not allowed: use default_factory') + + return f + + +def _find_fields(cls): + # Return a list of Field objects, in order, for this class (and no + # base classes). Fields are found from __annotations__ (which is + # guaranteed to be ordered). Default values are from class + # attributes, if a field has a default. If the default value is + # a Field(), then it contains additional info beyond (and + # possibly including) the actual default value. Pseudo-fields + # ClassVars and InitVars are included, despite the fact that + # they're not real fields. That's deal with later. + + annotations = getattr(cls, '__annotations__', {}) + + return [_get_field(cls, a_name, a_type) + for a_name, a_type in annotations.items()] + + +def _set_attribute(cls, name, value): + # Raise TypeError if an attribute by this name already exists. + if name in cls.__dict__: + raise TypeError(f'Cannot overwrite attribute {name} ' + f'in {cls.__name__}') + setattr(cls, name, value) + + +def _process_class(cls, repr, eq, order, hash, init, frozen): + # Use an OrderedDict because: + # - Order matters! + # - Derived class fields overwrite base class fields, but the + # order is defined by the base class, which is found first. + fields = collections.OrderedDict() + + # Find our base classes in reverse MRO order, and exclude + # ourselves. In reversed order so that more derived classes + # override earlier field definitions in base classes. + for b in cls.__mro__[-1:0:-1]: + # Only process classes that have been processed by our + # decorator. That is, they have a _MARKER attribute. + base_fields = getattr(b, _MARKER, None) + if base_fields: + for f in base_fields.values(): + fields[f.name] = f + + # Now find fields in our class. While doing so, validate some + # things, and set the default values (as class attributes) + # where we can. + for f in _find_fields(cls): + fields[f.name] = f + + # If the class attribute (which is the default value for + # this field) exists and is of type 'Field', replace it + # with the real default. This is so that normal class + # introspection sees a real default value, not a Field. + if isinstance(getattr(cls, f.name, None), Field): + if f.default is _MISSING: + # If there's no default, delete the class attribute. + # This happens if we specify field(repr=False), for + # example (that is, we specified a field object, but + # no default value). Also if we're using a default + # factory. The class attribute should not be set at + # all in the post-processed class. + delattr(cls, f.name) + else: + setattr(cls, f.name, f.default) + + # Remember all of the fields on our class (including bases). This + # marks this class as being a dataclass. + setattr(cls, _MARKER, fields) + + # We also need to check if a parent class is frozen: frozen has to + # be inherited down. + is_frozen = frozen or cls.__setattr__ is _frozen_setattr + + # If we're generating ordering methods, we must be generating + # the eq methods. + if order and not eq: + raise ValueError('eq must be true if order is true') + + if init: + # Does this class have a post-init function? + has_post_init = hasattr(cls, _POST_INIT_NAME) + + # Include InitVars and regular fields (so, not ClassVars). + _set_attribute(cls, '__init__', + _init_fn(list(filter(lambda f: f._field_type + in (_FIELD, _FIELD_INITVAR), + fields.values())), + is_frozen, + has_post_init, + # The name to use for the "self" param + # in __init__. Use "self" if possible. + '__dataclass_self__' if 'self' in fields + else 'self', + )) + + # Get the fields as a list, and include only real fields. This is + # used in all of the following methods. + field_list = list(filter(lambda f: f._field_type is _FIELD, + fields.values())) + + if repr: + _set_attribute(cls, '__repr__', + _repr_fn(list(filter(lambda f: f.repr, field_list)))) + + if is_frozen: + _set_attribute(cls, '__setattr__', _frozen_setattr) + _set_attribute(cls, '__delattr__', _frozen_delattr) + + generate_hash = False + if hash is None: + if eq and frozen: + # Generate a hash function. + generate_hash = True + elif eq and not frozen: + # Not hashable. + _set_attribute(cls, '__hash__', None) + elif not eq: + # Otherwise, use the base class definition of hash(). That is, + # don't set anything on this class. + pass + else: + assert "can't get here" + else: + generate_hash = hash + if generate_hash: + _set_attribute(cls, '__hash__', + _hash_fn(list(filter(lambda f: f.compare + if f.hash is None + else f.hash, + field_list)))) + + if eq: + # Create and __eq__ and __ne__ methods. + _set_eq_fns(cls, list(filter(lambda f: f.compare, field_list))) + + if order: + # Create and __lt__, __le__, __gt__, and __ge__ methods. + # Create and set the comparison functions. + _set_order_fns(cls, list(filter(lambda f: f.compare, field_list))) + + if not getattr(cls, '__doc__'): + # Create a class doc-string. + cls.__doc__ = (cls.__name__ + + str(inspect.signature(cls)).replace(' -> None', '')) + + return cls + + +# _cls should never be specified by keyword, so start it with an +# underscore. The presense of _cls is used to detect if this +# decorator is being called with parameters or not. +def dataclass(_cls=None, *, init=True, repr=True, eq=True, order=False, + hash=None, frozen=False): + """Returns the same class as was passed in, with dunder methods + added based on the fields defined in the class. + + Examines PEP 526 __annotations__ to determine fields. + + If init is true, an __init__() method is added to the class. If + repr is true, a __repr__() method is added. If order is true, rich + comparison dunder methods are added. If hash is true, a __hash__() + method function is added. If frozen is true, fields may not be + assigned to after instance creation. + """ + + def wrap(cls): + return _process_class(cls, repr, eq, order, hash, init, frozen) + + # See if we're being called as @dataclass or @dataclass(). + if _cls is None: + # We're called with parens. + return wrap + + # We're called as @dataclass without parens. + return wrap(_cls) + + +def fields(class_or_instance): + """Return a tuple describing the fields of this dataclass. + + Accepts a dataclass or an instance of one. Tuple elements are of + type Field. + """ + + # Might it be worth caching this, per class? + try: + fields = getattr(class_or_instance, _MARKER) + except AttributeError: + raise TypeError('must be called with a dataclass type or instance') + + # Exclude pseudo-fields. + return tuple(f for f in fields.values() if f._field_type is _FIELD) + + +def _isdataclass(obj): + """Returns True if obj is an instance of a dataclass.""" + return not isinstance(obj, type) and hasattr(obj, _MARKER) + + +def asdict(obj, *, dict_factory=dict): + """Return the fields of a dataclass instance as a new dictionary mapping + field names to field values. + + Example usage: + + @dataclass + class C: + x: int + y: int + + c = C(1, 2) + assert asdict(c) == {'x': 1, 'y': 2} + + If given, 'dict_factory' will be used instead of built-in dict. + The function applies recursively to field values that are + dataclass instances. This will also look into built-in containers: + tuples, lists, and dicts. + """ + if not _isdataclass(obj): + raise TypeError("asdict() should be called on dataclass instances") + return _asdict_inner(obj, dict_factory) + +def _asdict_inner(obj, dict_factory): + if _isdataclass(obj): + result = [] + for f in fields(obj): + value = _asdict_inner(getattr(obj, f.name), dict_factory) + result.append((f.name, value)) + return dict_factory(result) + elif isinstance(obj, (list, tuple)): + return type(obj)(_asdict_inner(v, dict_factory) for v in obj) + elif isinstance(obj, dict): + return type(obj)((_asdict_inner(k, dict_factory), _asdict_inner(v, dict_factory)) + for k, v in obj.items()) + else: + return deepcopy(obj) + + +def astuple(obj, *, tuple_factory=tuple): + """Return the fields of a dataclass instance as a new tuple of field values. + + Example usage:: + + @dataclass + class C: + x: int + y: int + + c = C(1, 2) + assert asdtuple(c) == (1, 2) + + If given, 'tuple_factory' will be used instead of built-in tuple. + The function applies recursively to field values that are + dataclass instances. This will also look into built-in containers: + tuples, lists, and dicts. + """ + + if not _isdataclass(obj): + raise TypeError("astuple() should be called on dataclass instances") + return _astuple_inner(obj, tuple_factory) + +def _astuple_inner(obj, tuple_factory): + if _isdataclass(obj): + result = [] + for f in fields(obj): + value = _astuple_inner(getattr(obj, f.name), tuple_factory) + result.append(value) + return tuple_factory(result) + elif isinstance(obj, (list, tuple)): + return type(obj)(_astuple_inner(v, tuple_factory) for v in obj) + elif isinstance(obj, dict): + return type(obj)((_astuple_inner(k, tuple_factory), _astuple_inner(v, tuple_factory)) + for k, v in obj.items()) + else: + return deepcopy(obj) + + +def make_dataclass(cls_name, fields, *, bases=(), namespace=None): + """Return a new dynamically created dataclass. + + The dataclass name will be 'cls_name'. 'fields' is an interable + of either (name, type) or (name, type, Field) objects. Field + objects are created by calling 'field(name, type [, Field])'. + + C = make_class('C', [('a', int', ('b', int, Field(init=False))], bases=Base) + + is equivalent to: + + @dataclass + class C(Base): + a: int + b: int = field(init=False) + + For the bases and namespace paremeters, see the builtin type() function. + """ + + if namespace is None: + namespace = {} + else: + # Copy namespace since we're going to mutate it. + namespace = namespace.copy() + + anns = collections.OrderedDict((name, tp) for name, tp, *_ in fields) + namespace['__annotations__'] = anns + for item in fields: + if len(item) == 3: + name, tp, spec = item + namespace[name] = spec + cls = type(cls_name, bases, namespace) + return dataclass(cls) + + +def replace(obj, **changes): + """Return a new object replacing specified fields with new values. + + This is especially useful for frozen classes. Example usage: + + @dataclass(frozen=True) + class C: + x: int + y: int + + c = C(1, 2) + c1 = replace(c, x=3) + assert c1.x == 3 and c1.y == 2 + """ + + # We're going to mutate 'changes', but that's okay because it's a new + # dict, even if called with 'replace(obj, **my_changes)'. + + if not _isdataclass(obj): + raise TypeError("replace() should be called on dataclass instances") + + # It's an error to have init=False fields in 'changes'. + # If a field is not in 'changes', read its value from the provided obj. + + for f in getattr(obj, _MARKER).values(): + if not f.init: + # Error if this field is specified in changes. + if f.name in changes: + raise ValueError(f'field {f.name} is declared with ' + 'init=False, it cannot be specified with ' + 'replace()') + continue + + if f.name not in changes: + changes[f.name] = getattr(obj, f.name) + + # Create the new object, which calls __init__() and __post_init__ + # (if defined), using all of the init fields we've added and/or + # left in 'changes'. + # If there are values supplied in changes that aren't fields, this + # will correctly raise a TypeError. + return obj.__class__(**changes) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py new file mode 100755 index 00000000000..caea98a13b0 --- /dev/null +++ b/Lib/test/test_dataclasses.py @@ -0,0 +1,2076 @@ +from dataclasses import ( + dataclass, field, FrozenInstanceError, fields, asdict, astuple, + make_dataclass, replace, InitVar, Field +) + +import pickle +import inspect +import unittest +from unittest.mock import Mock +from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar +from collections import deque, OrderedDict, namedtuple + +# Just any custom exception we can catch. +class CustomError(Exception): pass + +class TestCase(unittest.TestCase): + def test_no_fields(self): + @dataclass + class C: + pass + + o = C() + self.assertEqual(len(fields(C)), 0) + + def test_one_field_no_default(self): + @dataclass + class C: + x: int + + o = C(42) + self.assertEqual(o.x, 42) + + def test_named_init_params(self): + @dataclass + class C: + x: int + + o = C(x=32) + self.assertEqual(o.x, 32) + + def test_two_fields_one_default(self): + @dataclass + class C: + x: int + y: int = 0 + + o = C(3) + self.assertEqual((o.x, o.y), (3, 0)) + + # Non-defaults following defaults. + with self.assertRaisesRegex(TypeError, + "non-default argument 'y' follows " + "default argument"): + @dataclass + class C: + x: int = 0 + y: int + + # A derived class adds a non-default field after a default one. + with self.assertRaisesRegex(TypeError, + "non-default argument 'y' follows " + "default argument"): + @dataclass + class B: + x: int = 0 + + @dataclass + class C(B): + y: int + + # Override a base class field and add a default to + # a field which didn't use to have a default. + with self.assertRaisesRegex(TypeError, + "non-default argument 'y' follows " + "default argument"): + @dataclass + class B: + x: int + y: int + + @dataclass + class C(B): + x: int = 0 + + def test_overwriting_init(self): + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __init__ ' + 'in C'): + @dataclass + class C: + x: int + def __init__(self, x): + self.x = 2 * x + + @dataclass(init=False) + class C: + x: int + def __init__(self, x): + self.x = 2 * x + self.assertEqual(C(5).x, 10) + + def test_overwriting_repr(self): + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __repr__ ' + 'in C'): + @dataclass + class C: + x: int + def __repr__(self): + pass + + @dataclass(repr=False) + class C: + x: int + def __repr__(self): + return 'x' + self.assertEqual(repr(C(0)), 'x') + + def test_overwriting_cmp(self): + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __eq__ ' + 'in C'): + # This will generate the comparison functions, make sure we can't + # overwrite them. + @dataclass(hash=False, frozen=False) + class C: + x: int + def __eq__(self): + pass + + @dataclass(order=False, eq=False) + class C: + x: int + def __eq__(self, other): + return True + self.assertEqual(C(0), 'x') + + def test_overwriting_hash(self): + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__ ' + 'in C'): + @dataclass(frozen=True) + class C: + x: int + def __hash__(self): + pass + + @dataclass(frozen=True,hash=False) + class C: + x: int + def __hash__(self): + return 600 + self.assertEqual(hash(C(0)), 600) + + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__ ' + 'in C'): + @dataclass(frozen=True) + class C: + x: int + def __hash__(self): + pass + + @dataclass(frozen=True, hash=False) + class C: + x: int + def __hash__(self): + return 600 + self.assertEqual(hash(C(0)), 600) + + def test_overwriting_frozen(self): + # frozen uses __setattr__ and __delattr__ + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __setattr__ ' + 'in C'): + @dataclass(frozen=True) + class C: + x: int + def __setattr__(self): + pass + + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __delattr__ ' + 'in C'): + @dataclass(frozen=True) + class C: + x: int + def __delattr__(self): + pass + + @dataclass(frozen=False) + class C: + x: int + def __setattr__(self, name, value): + self.__dict__['x'] = value * 2 + self.assertEqual(C(10).x, 20) + + def test_overwrite_fields_in_derived_class(self): + # Note that x from C1 replaces x in Base, but the order remains + # the same as defined in Base. + @dataclass + class Base: + x: Any = 15.0 + y: int = 0 + + @dataclass + class C1(Base): + z: int = 10 + x: int = 15 + + o = Base() + self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..Base(x=15.0, y=0)') + + o = C1() + self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=15, y=0, z=10)') + + o = C1(x=5) + self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=5, y=0, z=10)') + + def test_field_named_self(self): + @dataclass + class C: + self: str + c=C('foo') + self.assertEqual(c.self, 'foo') + + # Make sure the first parameter is not named 'self'. + sig = inspect.signature(C.__init__) + first = next(iter(sig.parameters)) + self.assertNotEqual('self', first) + + # But we do use 'self' if no field named self. + @dataclass + class C: + selfx: str + + # Make sure the first parameter is named 'self'. + sig = inspect.signature(C.__init__) + first = next(iter(sig.parameters)) + self.assertEqual('self', first) + + def test_repr(self): + @dataclass + class B: + x: int + + @dataclass + class C(B): + y: int = 10 + + o = C(4) + self.assertEqual(repr(o), 'TestCase.test_repr..C(x=4, y=10)') + + @dataclass + class D(C): + x: int = 20 + self.assertEqual(repr(D()), 'TestCase.test_repr..D(x=20, y=10)') + + @dataclass + class C: + @dataclass + class D: + i: int + @dataclass + class E: + pass + self.assertEqual(repr(C.D(0)), 'TestCase.test_repr..C.D(i=0)') + self.assertEqual(repr(C.E()), 'TestCase.test_repr..C.E()') + + def test_0_field_compare(self): + # Ensure that order=False is the default. + @dataclass + class C0: + pass + + @dataclass(order=False) + class C1: + pass + + for cls in [C0, C1]: + with self.subTest(cls=cls): + self.assertEqual(cls(), cls()) + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + fn(cls(), cls()) + + @dataclass(order=True) + class C: + pass + self.assertLessEqual(C(), C()) + self.assertGreaterEqual(C(), C()) + + def test_1_field_compare(self): + # Ensure that order=False is the default. + @dataclass + class C0: + x: int + + @dataclass(order=False) + class C1: + x: int + + for cls in [C0, C1]: + with self.subTest(cls=cls): + self.assertEqual(cls(1), cls(1)) + self.assertNotEqual(cls(0), cls(1)) + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + fn(cls(0), cls(0)) + + @dataclass(order=True) + class C: + x: int + self.assertLess(C(0), C(1)) + self.assertLessEqual(C(0), C(1)) + self.assertLessEqual(C(1), C(1)) + self.assertGreater(C(1), C(0)) + self.assertGreaterEqual(C(1), C(0)) + self.assertGreaterEqual(C(1), C(1)) + + def test_simple_compare(self): + # Ensure that order=False is the default. + @dataclass + class C0: + x: int + y: int + + @dataclass(order=False) + class C1: + x: int + y: int + + for cls in [C0, C1]: + with self.subTest(cls=cls): + self.assertEqual(cls(0, 0), cls(0, 0)) + self.assertEqual(cls(1, 2), cls(1, 2)) + self.assertNotEqual(cls(1, 0), cls(0, 0)) + self.assertNotEqual(cls(1, 0), cls(1, 1)) + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + fn(cls(0, 0), cls(0, 0)) + + @dataclass(order=True) + class C: + x: int + y: int + + for idx, fn in enumerate([lambda a, b: a == b, + lambda a, b: a <= b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + self.assertTrue(fn(C(0, 0), C(0, 0))) + + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a != b]): + with self.subTest(idx=idx): + self.assertTrue(fn(C(0, 0), C(0, 1))) + self.assertTrue(fn(C(0, 1), C(1, 0))) + self.assertTrue(fn(C(1, 0), C(1, 1))) + + for idx, fn in enumerate([lambda a, b: a > b, + lambda a, b: a >= b, + lambda a, b: a != b]): + with self.subTest(idx=idx): + self.assertTrue(fn(C(0, 1), C(0, 0))) + self.assertTrue(fn(C(1, 0), C(0, 1))) + self.assertTrue(fn(C(1, 1), C(1, 0))) + + def test_compare_subclasses(self): + # Comparisons fail for subclasses, even if no fields + # are added. + @dataclass + class B: + i: int + + @dataclass + class C(B): + pass + + for idx, (fn, expected) in enumerate([(lambda a, b: a == b, False), + (lambda a, b: a != b, True)]): + with self.subTest(idx=idx): + self.assertEqual(fn(B(0), C(0)), expected) + + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + "not supported between instances of 'B' and 'C'"): + fn(B(0), C(0)) + + def test_0_field_hash(self): + @dataclass(hash=True) + class C: + pass + self.assertEqual(hash(C()), hash(())) + + def test_1_field_hash(self): + @dataclass(hash=True) + class C: + x: int + self.assertEqual(hash(C(4)), hash((4,))) + self.assertEqual(hash(C(42)), hash((42,))) + + def test_hash(self): + @dataclass(hash=True) + class C: + x: int + y: str + self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo'))) + + def test_no_hash(self): + @dataclass(hash=None) + class C: + x: int + with self.assertRaisesRegex(TypeError, + "unhashable type: 'C'"): + hash(C(1)) + + def test_hash_rules(self): + # There are 24 cases of: + # hash=True/False/None + # eq=True/False + # order=True/False + # frozen=True/False + for (hash, eq, order, frozen, result ) in [ + (False, False, False, False, 'absent'), + (False, False, False, True, 'absent'), + (False, False, True, False, 'exception'), + (False, False, True, True, 'exception'), + (False, True, False, False, 'absent'), + (False, True, False, True, 'absent'), + (False, True, True, False, 'absent'), + (False, True, True, True, 'absent'), + (True, False, False, False, 'fn'), + (True, False, False, True, 'fn'), + (True, False, True, False, 'exception'), + (True, False, True, True, 'exception'), + (True, True, False, False, 'fn'), + (True, True, False, True, 'fn'), + (True, True, True, False, 'fn'), + (True, True, True, True, 'fn'), + (None, False, False, False, 'absent'), + (None, False, False, True, 'absent'), + (None, False, True, False, 'exception'), + (None, False, True, True, 'exception'), + (None, True, False, False, 'none'), + (None, True, False, True, 'fn'), + (None, True, True, False, 'none'), + (None, True, True, True, 'fn'), + ]: + with self.subTest(hash=hash, eq=eq, order=order, frozen=frozen): + if result == 'exception': + with self.assertRaisesRegex(ValueError, 'eq must be true if order is true'): + @dataclass(hash=hash, eq=eq, order=order, frozen=frozen) + class C: + pass + else: + @dataclass(hash=hash, eq=eq, order=order, frozen=frozen) + class C: + pass + + # See if the result matches what's expected. + if result == 'fn': + # __hash__ contains the function we generated. + self.assertIn('__hash__', C.__dict__) + self.assertIsNotNone(C.__dict__['__hash__']) + elif result == 'absent': + # __hash__ is not present in our class. + self.assertNotIn('__hash__', C.__dict__) + elif result == 'none': + # __hash__ is set to None. + self.assertIn('__hash__', C.__dict__) + self.assertIsNone(C.__dict__['__hash__']) + else: + assert False, f'unknown result {result!r}' + + def test_eq_order(self): + for (eq, order, result ) in [ + (False, False, 'neither'), + (False, True, 'exception'), + (True, False, 'eq_only'), + (True, True, 'both'), + ]: + with self.subTest(eq=eq, order=order): + if result == 'exception': + with self.assertRaisesRegex(ValueError, 'eq must be true if order is true'): + @dataclass(eq=eq, order=order) + class C: + pass + else: + @dataclass(eq=eq, order=order) + class C: + pass + + if result == 'neither': + self.assertNotIn('__eq__', C.__dict__) + self.assertNotIn('__ne__', C.__dict__) + self.assertNotIn('__lt__', C.__dict__) + self.assertNotIn('__le__', C.__dict__) + self.assertNotIn('__gt__', C.__dict__) + self.assertNotIn('__ge__', C.__dict__) + elif result == 'both': + self.assertIn('__eq__', C.__dict__) + self.assertIn('__ne__', C.__dict__) + self.assertIn('__lt__', C.__dict__) + self.assertIn('__le__', C.__dict__) + self.assertIn('__gt__', C.__dict__) + self.assertIn('__ge__', C.__dict__) + elif result == 'eq_only': + self.assertIn('__eq__', C.__dict__) + self.assertIn('__ne__', C.__dict__) + self.assertNotIn('__lt__', C.__dict__) + self.assertNotIn('__le__', C.__dict__) + self.assertNotIn('__gt__', C.__dict__) + self.assertNotIn('__ge__', C.__dict__) + else: + assert False, f'unknown result {result!r}' + + def test_field_no_default(self): + @dataclass + class C: + x: int = field() + + self.assertEqual(C(5).x, 5) + + with self.assertRaisesRegex(TypeError, + r"__init__\(\) missing 1 required " + "positional argument: 'x'"): + C() + + def test_field_default(self): + default = object() + @dataclass + class C: + x: object = field(default=default) + + self.assertIs(C.x, default) + c = C(10) + self.assertEqual(c.x, 10) + + # If we delete the instance attribute, we should then see the + # class attribute. + del c.x + self.assertIs(c.x, default) + + self.assertIs(C().x, default) + + def test_not_in_repr(self): + @dataclass + class C: + x: int = field(repr=False) + with self.assertRaises(TypeError): + C() + c = C(10) + self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C()') + + @dataclass + class C: + x: int = field(repr=False) + y: int + c = C(10, 20) + self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C(y=20)') + + def test_not_in_compare(self): + @dataclass + class C: + x: int = 0 + y: int = field(compare=False, default=4) + + self.assertEqual(C(), C(0, 20)) + self.assertEqual(C(1, 10), C(1, 20)) + self.assertNotEqual(C(3), C(4, 10)) + self.assertNotEqual(C(3, 10), C(4, 10)) + + def test_hash_field_rules(self): + # Test all 6 cases of: + # hash=True/False/None + # compare=True/False + for (hash_val, compare, result ) in [ + (True, False, 'field' ), + (True, True, 'field' ), + (False, False, 'absent'), + (False, True, 'absent'), + (None, False, 'absent'), + (None, True, 'field' ), + ]: + with self.subTest(hash_val=hash_val, compare=compare): + @dataclass(hash=True) + class C: + x: int = field(compare=compare, hash=hash_val, default=5) + + if result == 'field': + # __hash__ contains the field. + self.assertEqual(C(5).__hash__(), hash((5,))) + elif result == 'absent': + # The field is not present in the hash. + self.assertEqual(C(5).__hash__(), hash(())) + else: + assert False, f'unknown result {result!r}' + + def test_init_false_no_default(self): + # If init=False and no default value, then the field won't be + # present in the instance. + @dataclass + class C: + x: int = field(init=False) + + self.assertNotIn('x', C().__dict__) + + @dataclass + class C: + x: int + y: int = 0 + z: int = field(init=False) + t: int = 10 + + self.assertNotIn('z', C(0).__dict__) + self.assertEqual(vars(C(5)), {'t': 10, 'x': 5, 'y': 0}) + + def test_class_marker(self): + @dataclass + class C: + x: int + y: str = field(init=False, default=None) + z: str = field(repr=False) + + the_fields = fields(C) + # the_fields is a tuple of 3 items, each value + # is in __annotations__. + self.assertIsInstance(the_fields, tuple) + for f in the_fields: + self.assertIs(type(f), Field) + self.assertIn(f.name, C.__annotations__) + + self.assertEqual(len(the_fields), 3) + + self.assertEqual(the_fields[0].name, 'x') + self.assertEqual(the_fields[0].type, int) + self.assertFalse(hasattr(C, 'x')) + self.assertTrue (the_fields[0].init) + self.assertTrue (the_fields[0].repr) + self.assertEqual(the_fields[1].name, 'y') + self.assertEqual(the_fields[1].type, str) + self.assertIsNone(getattr(C, 'y')) + self.assertFalse(the_fields[1].init) + self.assertTrue (the_fields[1].repr) + self.assertEqual(the_fields[2].name, 'z') + self.assertEqual(the_fields[2].type, str) + self.assertFalse(hasattr(C, 'z')) + self.assertTrue (the_fields[2].init) + self.assertFalse(the_fields[2].repr) + + def test_field_order(self): + @dataclass + class B: + a: str = 'B:a' + b: str = 'B:b' + c: str = 'B:c' + + @dataclass + class C(B): + b: str = 'C:b' + + self.assertEqual([(f.name, f.default) for f in fields(C)], + [('a', 'B:a'), + ('b', 'C:b'), + ('c', 'B:c')]) + + @dataclass + class D(B): + c: str = 'D:c' + + self.assertEqual([(f.name, f.default) for f in fields(D)], + [('a', 'B:a'), + ('b', 'B:b'), + ('c', 'D:c')]) + + @dataclass + class E(D): + a: str = 'E:a' + d: str = 'E:d' + + self.assertEqual([(f.name, f.default) for f in fields(E)], + [('a', 'E:a'), + ('b', 'B:b'), + ('c', 'D:c'), + ('d', 'E:d')]) + + def test_class_attrs(self): + # We only have a class attribute if a default value is + # specified, either directly or via a field with a default. + default = object() + @dataclass + class C: + x: int + y: int = field(repr=False) + z: object = default + t: int = field(default=100) + + self.assertFalse(hasattr(C, 'x')) + self.assertFalse(hasattr(C, 'y')) + self.assertIs (C.z, default) + self.assertEqual(C.t, 100) + + def test_disallowed_mutable_defaults(self): + # For the known types, don't allow mutable default values. + for typ, empty, non_empty in [(list, [], [1]), + (dict, {}, {0:1}), + (set, set(), set([1])), + ]: + with self.subTest(typ=typ): + # Can't use a zero-length value. + with self.assertRaisesRegex(ValueError, + f'mutable default {typ} for field ' + 'x is not allowed'): + @dataclass + class Point: + x: typ = empty + + + # Nor a non-zero-length value + with self.assertRaisesRegex(ValueError, + f'mutable default {typ} for field ' + 'y is not allowed'): + @dataclass + class Point: + y: typ = non_empty + + # Check subtypes also fail. + class Subclass(typ): pass + + with self.assertRaisesRegex(ValueError, + f"mutable default .*Subclass'>" + ' for field z is not allowed' + ): + @dataclass + class Point: + z: typ = Subclass() + + # Because this is a ClassVar, it can be mutable. + @dataclass + class C: + z: ClassVar[typ] = typ() + + # Because this is a ClassVar, it can be mutable. + @dataclass + class C: + x: ClassVar[typ] = Subclass() + + + def test_deliberately_mutable_defaults(self): + # If a mutable default isn't in the known list of + # (list, dict, set), then it's okay. + class Mutable: + def __init__(self): + self.l = [] + + @dataclass + class C: + x: Mutable + + # These 2 instances will share this value of x. + lst = Mutable() + o1 = C(lst) + o2 = C(lst) + self.assertEqual(o1, o2) + o1.x.l.extend([1, 2]) + self.assertEqual(o1, o2) + self.assertEqual(o1.x.l, [1, 2]) + self.assertIs(o1.x, o2.x) + + def test_no_options(self): + # call with dataclass() + @dataclass() + class C: + x: int + + self.assertEqual(C(42).x, 42) + + def test_not_tuple(self): + # Make sure we can't be compared to a tuple. + @dataclass + class Point: + x: int + y: int + self.assertNotEqual(Point(1, 2), (1, 2)) + + # And that we can't compare to another unrelated dataclass + @dataclass + class C: + x: int + y: int + self.assertNotEqual(Point(1, 3), C(1, 3)) + + def test_base_has_init(self): + class B: + def __init__(self): + pass + + # Make sure that declaring this class doesn't raise an error. + # The issue is that we can't override __init__ in our class, + # but it should be okay to add __init__ to us if our base has + # an __init__. + @dataclass + class C(B): + x: int = 0 + + def test_frozen(self): + @dataclass(frozen=True) + class C: + i: int + + c = C(10) + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertEqual(c.i, 10) + + # Check that a derived class is still frozen, even if not + # marked so. + @dataclass + class D(C): + pass + + d = D(20) + self.assertEqual(d.i, 20) + with self.assertRaises(FrozenInstanceError): + d.i = 5 + self.assertEqual(d.i, 20) + + def test_not_tuple(self): + # Test that some of the problems with namedtuple don't happen + # here. + @dataclass + class Point3D: + x: int + y: int + z: int + + @dataclass + class Date: + year: int + month: int + day: int + + self.assertNotEqual(Point3D(2017, 6, 3), Date(2017, 6, 3)) + self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3)) + + # Make sure we can't unpack + with self.assertRaisesRegex(TypeError, 'is not iterable'): + x, y, z = Point3D(4, 5, 6) + + # Maka sure another class with the same field names isn't + # equal. + @dataclass + class Point3Dv1: + x: int = 0 + y: int = 0 + z: int = 0 + self.assertNotEqual(Point3D(0, 0, 0), Point3Dv1()) + + def test_function_annotations(self): + # Some dummy class and instance to use as a default. + class F: + pass + f = F() + + def validate_class(cls): + # First, check __annotations__, even though they're not + # function annotations. + self.assertEqual(cls.__annotations__['i'], int) + self.assertEqual(cls.__annotations__['j'], str) + self.assertEqual(cls.__annotations__['k'], F) + self.assertEqual(cls.__annotations__['l'], float) + self.assertEqual(cls.__annotations__['z'], complex) + + # Verify __init__. + + signature = inspect.signature(cls.__init__) + # Check the return type, should be None + self.assertIs(signature.return_annotation, None) + + # Check each parameter. + params = iter(signature.parameters.values()) + param = next(params) + # This is testing an internal name, and probably shouldn't be tested. + self.assertEqual(param.name, 'self') + param = next(params) + self.assertEqual(param.name, 'i') + self.assertIs (param.annotation, int) + self.assertEqual(param.default, inspect.Parameter.empty) + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + param = next(params) + self.assertEqual(param.name, 'j') + self.assertIs (param.annotation, str) + self.assertEqual(param.default, inspect.Parameter.empty) + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + param = next(params) + self.assertEqual(param.name, 'k') + self.assertIs (param.annotation, F) + # Don't test for the default, since it's set to _MISSING + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + param = next(params) + self.assertEqual(param.name, 'l') + self.assertIs (param.annotation, float) + # Don't test for the default, since it's set to _MISSING + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + self.assertRaises(StopIteration, next, params) + + + @dataclass + class C: + i: int + j: str + k: F = f + l: float=field(default=None) + z: complex=field(default=3+4j, init=False) + + validate_class(C) + + # Now repeat with __hash__. + @dataclass(frozen=True, hash=True) + class C: + i: int + j: str + k: F = f + l: float=field(default=None) + z: complex=field(default=3+4j, init=False) + + validate_class(C) + + def test_dont_include_other_annotations(self): + @dataclass + class C: + i: int + def foo(self) -> int: + return 4 + @property + def bar(self) -> int: + return 5 + self.assertEqual(list(C.__annotations__), ['i']) + self.assertEqual(C(10).foo(), 4) + self.assertEqual(C(10).bar, 5) + + def test_post_init(self): + # Just make sure it gets called + @dataclass + class C: + def __post_init__(self): + raise CustomError() + with self.assertRaises(CustomError): + C() + + @dataclass + class C: + i: int = 10 + def __post_init__(self): + if self.i == 10: + raise CustomError() + with self.assertRaises(CustomError): + C() + # post-init gets called, but doesn't raise. This is just + # checking that self is used correctly. + C(5) + + # If there's not an __init__, then post-init won't get called. + @dataclass(init=False) + class C: + def __post_init__(self): + raise CustomError() + # Creating the class won't raise + C() + + @dataclass + class C: + x: int = 0 + def __post_init__(self): + self.x *= 2 + self.assertEqual(C().x, 0) + self.assertEqual(C(2).x, 4) + + # Make sure that if we'r frozen, post-init can't set + # attributes. + @dataclass(frozen=True) + class C: + x: int = 0 + def __post_init__(self): + self.x *= 2 + with self.assertRaises(FrozenInstanceError): + C() + + def test_post_init_super(self): + # Make sure super() post-init isn't called by default. + class B: + def __post_init__(self): + raise CustomError() + + @dataclass + class C(B): + def __post_init__(self): + self.x = 5 + + self.assertEqual(C().x, 5) + + # Now call super(), and it will raise + @dataclass + class C(B): + def __post_init__(self): + super().__post_init__() + + with self.assertRaises(CustomError): + C() + + # Make sure post-init is called, even if not defined in our + # class. + @dataclass + class C(B): + pass + + with self.assertRaises(CustomError): + C() + + def test_post_init_staticmethod(self): + flag = False + @dataclass + class C: + x: int + y: int + @staticmethod + def __post_init__(): + nonlocal flag + flag = True + + self.assertFalse(flag) + c = C(3, 4) + self.assertEqual((c.x, c.y), (3, 4)) + self.assertTrue(flag) + + def test_post_init_classmethod(self): + @dataclass + class C: + flag = False + x: int + y: int + @classmethod + def __post_init__(cls): + cls.flag = True + + self.assertFalse(C.flag) + c = C(3, 4) + self.assertEqual((c.x, c.y), (3, 4)) + self.assertTrue(C.flag) + + def test_class_var(self): + # Make sure ClassVars are ignored in __init__, __repr__, etc. + @dataclass + class C: + x: int + y: int = 10 + z: ClassVar[int] = 1000 + w: ClassVar[int] = 2000 + t: ClassVar[int] = 3000 + + c = C(5) + self.assertEqual(repr(c), 'TestCase.test_class_var..C(x=5, y=10)') + self.assertEqual(len(fields(C)), 2) # We have 2 fields + self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars + self.assertEqual(c.z, 1000) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + C.z += 1 + self.assertEqual(c.z, 1001) + c = C(20) + self.assertEqual((c.x, c.y), (20, 10)) + self.assertEqual(c.z, 1001) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + + def test_class_var_no_default(self): + # If a ClassVar has no default value, it should not be set on the class. + @dataclass + class C: + x: ClassVar[int] + + self.assertNotIn('x', C.__dict__) + + def test_class_var_default_factory(self): + # It makes no sense for a ClassVar to have a default factory. When + # would it be called? Call it yourself, since it's class-wide. + with self.assertRaisesRegex(TypeError, + 'cannot have a default factory'): + @dataclass + class C: + x: ClassVar[int] = field(default_factory=int) + + self.assertNotIn('x', C.__dict__) + + def test_class_var_with_default(self): + # If a ClassVar has a default value, it should be set on the class. + @dataclass + class C: + x: ClassVar[int] = 10 + self.assertEqual(C.x, 10) + + @dataclass + class C: + x: ClassVar[int] = field(default=10) + self.assertEqual(C.x, 10) + + def test_class_var_frozen(self): + # Make sure ClassVars work even if we're frozen. + @dataclass(frozen=True) + class C: + x: int + y: int = 10 + z: ClassVar[int] = 1000 + w: ClassVar[int] = 2000 + t: ClassVar[int] = 3000 + + c = C(5) + self.assertEqual(repr(C(5)), 'TestCase.test_class_var_frozen..C(x=5, y=10)') + self.assertEqual(len(fields(C)), 2) # We have 2 fields + self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars + self.assertEqual(c.z, 1000) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + # We can still modify the ClassVar, it's only instances that are + # frozen. + C.z += 1 + self.assertEqual(c.z, 1001) + c = C(20) + self.assertEqual((c.x, c.y), (20, 10)) + self.assertEqual(c.z, 1001) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + + def test_init_var_no_default(self): + # If an InitVar has no default value, it should not be set on the class. + @dataclass + class C: + x: InitVar[int] + + self.assertNotIn('x', C.__dict__) + + def test_init_var_default_factory(self): + # It makes no sense for an InitVar to have a default factory. When + # would it be called? Call it yourself, since it's class-wide. + with self.assertRaisesRegex(TypeError, + 'cannot have a default factory'): + @dataclass + class C: + x: InitVar[int] = field(default_factory=int) + + self.assertNotIn('x', C.__dict__) + + def test_init_var_with_default(self): + # If an InitVar has a default value, it should be set on the class. + @dataclass + class C: + x: InitVar[int] = 10 + self.assertEqual(C.x, 10) + + @dataclass + class C: + x: InitVar[int] = field(default=10) + self.assertEqual(C.x, 10) + + def test_init_var(self): + @dataclass + class C: + x: int = None + init_param: InitVar[int] = None + + def __post_init__(self, init_param): + if self.x is None: + self.x = init_param*2 + + c = C(init_param=10) + self.assertEqual(c.x, 20) + + def test_init_var_inheritance(self): + # Note that this deliberately tests that a dataclass need not + # have a __post_init__ function if it has an InitVar field. + # It could just be used in a derived class, as shown here. + @dataclass + class Base: + x: int + init_base: InitVar[int] + + # We can instantiate by passing the InitVar, even though + # it's not used. + b = Base(0, 10) + self.assertEqual(vars(b), {'x': 0}) + + @dataclass + class C(Base): + y: int + init_derived: InitVar[int] + + def __post_init__(self, init_base, init_derived): + self.x = self.x + init_base + self.y = self.y + init_derived + + c = C(10, 11, 50, 51) + self.assertEqual(vars(c), {'x': 21, 'y': 101}) + + def test_default_factory(self): + # Test a factory that returns a new list. + @dataclass + class C: + x: int + y: list = field(default_factory=list) + + c0 = C(3) + c1 = C(3) + self.assertEqual(c0.x, 3) + self.assertEqual(c0.y, []) + self.assertEqual(c0, c1) + self.assertIsNot(c0.y, c1.y) + self.assertEqual(astuple(C(5, [1])), (5, [1])) + + # Test a factory that returns a shared list. + l = [] + @dataclass + class C: + x: int + y: list = field(default_factory=lambda: l) + + c0 = C(3) + c1 = C(3) + self.assertEqual(c0.x, 3) + self.assertEqual(c0.y, []) + self.assertEqual(c0, c1) + self.assertIs(c0.y, c1.y) + self.assertEqual(astuple(C(5, [1])), (5, [1])) + + # Test various other field flags. + # repr + @dataclass + class C: + x: list = field(default_factory=list, repr=False) + self.assertEqual(repr(C()), 'TestCase.test_default_factory..C()') + self.assertEqual(C().x, []) + + # hash + @dataclass(hash=True) + class C: + x: list = field(default_factory=list, hash=False) + self.assertEqual(astuple(C()), ([],)) + self.assertEqual(hash(C()), hash(())) + + # init (see also test_default_factory_with_no_init) + @dataclass + class C: + x: list = field(default_factory=list, init=False) + self.assertEqual(astuple(C()), ([],)) + + # compare + @dataclass + class C: + x: list = field(default_factory=list, compare=False) + self.assertEqual(C(), C([1])) + + def test_default_factory_with_no_init(self): + # We need a factory with a side effect. + factory = Mock() + + @dataclass + class C: + x: list = field(default_factory=factory, init=False) + + # Make sure the default factory is called for each new instance. + C().x + self.assertEqual(factory.call_count, 1) + C().x + self.assertEqual(factory.call_count, 2) + + def test_default_factory_not_called_if_value_given(self): + # We need a factory that we can test if it's been called. + factory = Mock() + + @dataclass + class C: + x: int = field(default_factory=factory) + + # Make sure that if a field has a default factory function, + # it's not called if a value is specified. + C().x + self.assertEqual(factory.call_count, 1) + self.assertEqual(C(10).x, 10) + self.assertEqual(factory.call_count, 1) + C().x + self.assertEqual(factory.call_count, 2) + + def x_test_classvar_default_factory(self): + # XXX: it's an error for a ClassVar to have a factory function + @dataclass + class C: + x: ClassVar[int] = field(default_factory=int) + + self.assertIs(C().x, int) + + def test_isdataclass(self): + # There is no isdataclass() helper any more, but the PEP + # describes how to write it, so make sure that works. Note + # that this version returns True for both classes and + # instances. + def isdataclass(obj): + try: + fields(obj) + return True + except TypeError: + return False + + self.assertFalse(isdataclass(0)) + self.assertFalse(isdataclass(int)) + + @dataclass + class C: + x: int + + self.assertTrue(isdataclass(C)) + self.assertTrue(isdataclass(C(0))) + + def test_helper_fields_with_class_instance(self): + # Check that we can call fields() on either a class or instance, + # and get back the same thing. + @dataclass + class C: + x: int + y: float + + self.assertEqual(fields(C), fields(C(0, 0.0))) + + def test_helper_fields_exception(self): + # Check that TypeError is raised if not passed a dataclass or + # instance. + with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + fields(0) + + class C: pass + with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + fields(C) + with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + fields(C()) + + def test_helper_asdict(self): + # Basic tests for asdict(), it should return a new dictionary + @dataclass + class C: + x: int + y: int + c = C(1, 2) + + self.assertEqual(asdict(c), {'x': 1, 'y': 2}) + self.assertEqual(asdict(c), asdict(c)) + self.assertIsNot(asdict(c), asdict(c)) + c.x = 42 + self.assertEqual(asdict(c), {'x': 42, 'y': 2}) + self.assertIs(type(asdict(c)), dict) + + def test_helper_asdict_raises_on_classes(self): + # asdict() should raise on a class object + @dataclass + class C: + x: int + y: int + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + asdict(C) + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + asdict(int) + + def test_helper_asdict_copy_values(self): + @dataclass + class C: + x: int + y: List[int] = field(default_factory=list) + initial = [] + c = C(1, initial) + d = asdict(c) + self.assertEqual(d['y'], initial) + self.assertIsNot(d['y'], initial) + c = C(1) + d = asdict(c) + d['y'].append(1) + self.assertEqual(c.y, []) + + def test_helper_asdict_nested(self): + @dataclass + class UserId: + token: int + group: int + @dataclass + class User: + name: str + id: UserId + u = User('Joe', UserId(123, 1)) + d = asdict(u) + self.assertEqual(d, {'name': 'Joe', 'id': {'token': 123, 'group': 1}}) + self.assertIsNot(asdict(u), asdict(u)) + u.id.group = 2 + self.assertEqual(asdict(u), {'name': 'Joe', + 'id': {'token': 123, 'group': 2}}) + + def test_helper_asdict_builtin_containers(self): + @dataclass + class User: + name: str + id: int + @dataclass + class GroupList: + id: int + users: List[User] + @dataclass + class GroupTuple: + id: int + users: Tuple[User, ...] + @dataclass + class GroupDict: + id: int + users: Dict[str, User] + a = User('Alice', 1) + b = User('Bob', 2) + gl = GroupList(0, [a, b]) + gt = GroupTuple(0, (a, b)) + gd = GroupDict(0, {'first': a, 'second': b}) + self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1}, + {'name': 'Bob', 'id': 2}]}) + self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1}, + {'name': 'Bob', 'id': 2})}) + self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, + 'second': {'name': 'Bob', 'id': 2}}}) + + def test_helper_asdict_builtin_containers(self): + @dataclass + class Child: + d: object + + @dataclass + class Parent: + child: Child + + self.assertEqual(asdict(Parent(Child([1]))), {'child': {'d': [1]}}) + self.assertEqual(asdict(Parent(Child({1: 2}))), {'child': {'d': {1: 2}}}) + + def test_helper_asdict_factory(self): + @dataclass + class C: + x: int + y: int + c = C(1, 2) + d = asdict(c, dict_factory=OrderedDict) + self.assertEqual(d, OrderedDict([('x', 1), ('y', 2)])) + self.assertIsNot(d, asdict(c, dict_factory=OrderedDict)) + c.x = 42 + d = asdict(c, dict_factory=OrderedDict) + self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)])) + self.assertIs(type(d), OrderedDict) + + def test_helper_astuple(self): + # Basic tests for astuple(), it should return a new tuple + @dataclass + class C: + x: int + y: int = 0 + c = C(1) + + self.assertEqual(astuple(c), (1, 0)) + self.assertEqual(astuple(c), astuple(c)) + self.assertIsNot(astuple(c), astuple(c)) + c.y = 42 + self.assertEqual(astuple(c), (1, 42)) + self.assertIs(type(astuple(c)), tuple) + + def test_helper_astuple_raises_on_classes(self): + # astuple() should raise on a class object + @dataclass + class C: + x: int + y: int + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + astuple(C) + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + astuple(int) + + def test_helper_astuple_copy_values(self): + @dataclass + class C: + x: int + y: List[int] = field(default_factory=list) + initial = [] + c = C(1, initial) + t = astuple(c) + self.assertEqual(t[1], initial) + self.assertIsNot(t[1], initial) + c = C(1) + t = astuple(c) + t[1].append(1) + self.assertEqual(c.y, []) + + def test_helper_astuple_nested(self): + @dataclass + class UserId: + token: int + group: int + @dataclass + class User: + name: str + id: UserId + u = User('Joe', UserId(123, 1)) + t = astuple(u) + self.assertEqual(t, ('Joe', (123, 1))) + self.assertIsNot(astuple(u), astuple(u)) + u.id.group = 2 + self.assertEqual(astuple(u), ('Joe', (123, 2))) + + def test_helper_astuple_builtin_containers(self): + @dataclass + class User: + name: str + id: int + @dataclass + class GroupList: + id: int + users: List[User] + @dataclass + class GroupTuple: + id: int + users: Tuple[User, ...] + @dataclass + class GroupDict: + id: int + users: Dict[str, User] + a = User('Alice', 1) + b = User('Bob', 2) + gl = GroupList(0, [a, b]) + gt = GroupTuple(0, (a, b)) + gd = GroupDict(0, {'first': a, 'second': b}) + self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)])) + self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2)))) + self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)})) + + def test_helper_astuple_builtin_containers(self): + @dataclass + class Child: + d: object + + @dataclass + class Parent: + child: Child + + self.assertEqual(astuple(Parent(Child([1]))), (([1],),)) + self.assertEqual(astuple(Parent(Child({1: 2}))), (({1: 2},),)) + + def test_helper_astuple_factory(self): + @dataclass + class C: + x: int + y: int + NT = namedtuple('NT', 'x y') + def nt(lst): + return NT(*lst) + c = C(1, 2) + t = astuple(c, tuple_factory=nt) + self.assertEqual(t, NT(1, 2)) + self.assertIsNot(t, astuple(c, tuple_factory=nt)) + c.x = 42 + t = astuple(c, tuple_factory=nt) + self.assertEqual(t, NT(42, 2)) + self.assertIs(type(t), NT) + + def test_dynamic_class_creation(self): + cls_dict = {'__annotations__': OrderedDict(x=int, y=int), + } + + # Create the class. + cls = type('C', (), cls_dict) + + # Make it a dataclass. + cls1 = dataclass(cls) + + self.assertEqual(cls1, cls) + self.assertEqual(asdict(cls(1, 2)), {'x': 1, 'y': 2}) + + def test_dynamic_class_creation_using_field(self): + cls_dict = {'__annotations__': OrderedDict(x=int, y=int), + 'y': field(default=5), + } + + # Create the class. + cls = type('C', (), cls_dict) + + # Make it a dataclass. + cls1 = dataclass(cls) + + self.assertEqual(cls1, cls) + self.assertEqual(asdict(cls1(1)), {'x': 1, 'y': 5}) + + def test_init_in_order(self): + @dataclass + class C: + a: int + b: int = field() + c: list = field(default_factory=list, init=False) + d: list = field(default_factory=list) + e: int = field(default=4, init=False) + f: int = 4 + + calls = [] + def setattr(self, name, value): + calls.append((name, value)) + + C.__setattr__ = setattr + c = C(0, 1) + self.assertEqual(('a', 0), calls[0]) + self.assertEqual(('b', 1), calls[1]) + self.assertEqual(('c', []), calls[2]) + self.assertEqual(('d', []), calls[3]) + self.assertNotIn(('e', 4), calls) + self.assertEqual(('f', 4), calls[4]) + + def test_items_in_dicts(self): + @dataclass + class C: + a: int + b: list = field(default_factory=list, init=False) + c: list = field(default_factory=list) + d: int = field(default=4, init=False) + e: int = 0 + + c = C(0) + # Class dict + self.assertNotIn('a', C.__dict__) + self.assertNotIn('b', C.__dict__) + self.assertNotIn('c', C.__dict__) + self.assertIn('d', C.__dict__) + self.assertEqual(C.d, 4) + self.assertIn('e', C.__dict__) + self.assertEqual(C.e, 0) + # Instance dict + self.assertIn('a', c.__dict__) + self.assertEqual(c.a, 0) + self.assertIn('b', c.__dict__) + self.assertEqual(c.b, []) + self.assertIn('c', c.__dict__) + self.assertEqual(c.c, []) + self.assertNotIn('d', c.__dict__) + self.assertIn('e', c.__dict__) + self.assertEqual(c.e, 0) + + def test_alternate_classmethod_constructor(self): + # Since __post_init__ can't take params, use a classmethod + # alternate constructor. This is mostly an example to show how + # to use this technique. + @dataclass + class C: + x: int + @classmethod + def from_file(cls, filename): + # In a real example, create a new instance + # and populate 'x' from contents of a file. + value_in_file = 20 + return cls(value_in_file) + + self.assertEqual(C.from_file('filename').x, 20) + + def test_field_metadata_default(self): + # Make sure the default metadata is read-only and of + # zero length. + @dataclass + class C: + i: int + + self.assertFalse(fields(C)[0].metadata) + self.assertEqual(len(fields(C)[0].metadata), 0) + with self.assertRaisesRegex(TypeError, + 'does not support item assignment'): + fields(C)[0].metadata['test'] = 3 + + def test_field_metadata_mapping(self): + # Make sure only a mapping can be passed as metadata + # zero length. + with self.assertRaises(TypeError): + @dataclass + class C: + i: int = field(metadata=0) + + # Make sure an empty dict works + @dataclass + class C: + i: int = field(metadata={}) + self.assertFalse(fields(C)[0].metadata) + self.assertEqual(len(fields(C)[0].metadata), 0) + with self.assertRaisesRegex(TypeError, + 'does not support item assignment'): + fields(C)[0].metadata['test'] = 3 + + # Make sure a non-empty dict works. + @dataclass + class C: + i: int = field(metadata={'test': 10, 'bar': '42', 3: 'three'}) + self.assertEqual(len(fields(C)[0].metadata), 3) + self.assertEqual(fields(C)[0].metadata['test'], 10) + self.assertEqual(fields(C)[0].metadata['bar'], '42') + self.assertEqual(fields(C)[0].metadata[3], 'three') + with self.assertRaises(KeyError): + # Non-existent key. + fields(C)[0].metadata['baz'] + with self.assertRaisesRegex(TypeError, + 'does not support item assignment'): + fields(C)[0].metadata['test'] = 3 + + def test_field_metadata_custom_mapping(self): + # Try a custom mapping. + class SimpleNameSpace: + def __init__(self, **kw): + self.__dict__.update(kw) + + def __getitem__(self, item): + if item == 'xyzzy': + return 'plugh' + return getattr(self, item) + + def __len__(self): + return self.__dict__.__len__() + + @dataclass + class C: + i: int = field(metadata=SimpleNameSpace(a=10)) + + self.assertEqual(len(fields(C)[0].metadata), 1) + self.assertEqual(fields(C)[0].metadata['a'], 10) + with self.assertRaises(AttributeError): + fields(C)[0].metadata['b'] + # Make sure we're still talking to our custom mapping. + self.assertEqual(fields(C)[0].metadata['xyzzy'], 'plugh') + + def test_generic_dataclasses(self): + T = TypeVar('T') + + @dataclass + class LabeledBox(Generic[T]): + content: T + label: str = '' + + box = LabeledBox(42) + self.assertEqual(box.content, 42) + self.assertEqual(box.label, '') + + # subscripting the resulting class should work, etc. + Alias = List[LabeledBox[int]] + + def test_generic_extending(self): + S = TypeVar('S') + T = TypeVar('T') + + @dataclass + class Base(Generic[T, S]): + x: T + y: S + + @dataclass + class DataDerived(Base[int, T]): + new_field: str + Alias = DataDerived[str] + c = Alias(0, 'test1', 'test2') + self.assertEqual(astuple(c), (0, 'test1', 'test2')) + + class NonDataDerived(Base[int, T]): + def new_method(self): + return self.y + Alias = NonDataDerived[float] + c = Alias(10, 1.0) + self.assertEqual(c.new_method(), 1.0) + + def test_helper_replace(self): + @dataclass(frozen=True) + class C: + x: int + y: int + + c = C(1, 2) + c1 = replace(c, x=3) + self.assertEqual(c1.x, 3) + self.assertEqual(c1.y, 2) + + def test_helper_replace_frozen(self): + @dataclass(frozen=True) + class C: + x: int + y: int + z: int = field(init=False, default=10) + t: int = field(init=False, default=100) + + c = C(1, 2) + c1 = replace(c, x=3) + self.assertEqual((c.x, c.y, c.z, c.t), (1, 2, 10, 100)) + self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100)) + + + with self.assertRaisesRegex(ValueError, 'init=False'): + replace(c, x=3, z=20, t=50) + with self.assertRaisesRegex(ValueError, 'init=False'): + replace(c, z=20) + replace(c, x=3, z=20, t=50) + + # Make sure the result is still frozen. + with self.assertRaisesRegex(FrozenInstanceError, "cannot assign to field 'x'"): + c1.x = 3 + + # Make sure we can't replace an attribute that doesn't exist, + # if we're also replacing one that does exist. Test this + # here, because setting attributes on frozen instances is + # handled slightly differently from non-frozen ones. + with self.assertRaisesRegex(TypeError, "__init__\(\) got an unexpected " + "keyword argument 'a'"): + c1 = replace(c, x=20, a=5) + + def test_helper_replace_invalid_field_name(self): + @dataclass(frozen=True) + class C: + x: int + y: int + + c = C(1, 2) + with self.assertRaisesRegex(TypeError, "__init__\(\) got an unexpected " + "keyword argument 'z'"): + c1 = replace(c, z=3) + + def test_helper_replace_invalid_object(self): + @dataclass(frozen=True) + class C: + x: int + y: int + + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + replace(C, x=3) + + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + replace(0, x=3) + + def test_helper_replace_no_init(self): + @dataclass + class C: + x: int + y: int = field(init=False, default=10) + + c = C(1) + c.y = 20 + + # Make sure y gets the default value. + c1 = replace(c, x=5) + self.assertEqual((c1.x, c1.y), (5, 10)) + + # Trying to replace y is an error. + with self.assertRaisesRegex(ValueError, 'init=False'): + replace(c, x=2, y=30) + with self.assertRaisesRegex(ValueError, 'init=False'): + replace(c, y=30) + + def test_dataclassses_pickleable(self): + global P, Q, R + @dataclass + class P: + x: int + y: int = 0 + @dataclass + class Q: + x: int + y: int = field(default=0, init=False) + @dataclass + class R: + x: int + y: List[int] = field(default_factory=list) + q = Q(1) + q.y = 2 + samples = [P(1), P(1, 2), Q(1), q, R(1), R(1, [2, 3, 4])] + for sample in samples: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(sample=sample, proto=proto): + new_sample = pickle.loads(pickle.dumps(sample, proto)) + self.assertEqual(sample.x, new_sample.x) + self.assertEqual(sample.y, new_sample.y) + self.assertIsNot(sample, new_sample) + new_sample.x = 42 + another_new_sample = pickle.loads(pickle.dumps(new_sample, proto)) + self.assertEqual(new_sample.x, another_new_sample.x) + self.assertEqual(sample.y, another_new_sample.y) + + def test_helper_make_dataclass(self): + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace={'add_one': lambda self: self.x + 1}) + c = C(10) + self.assertEqual((c.x, c.y), (10, 5)) + self.assertEqual(c.add_one(), 11) + + + def test_helper_make_dataclass_no_mutate_namespace(self): + # Make sure a provided namespace isn't mutated. + ns = {} + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace=ns) + self.assertEqual(ns, {}) + + def test_helper_make_dataclass_base(self): + class Base1: + pass + class Base2: + pass + C = make_dataclass('C', + [('x', int)], + bases=(Base1, Base2)) + c = C(2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + def test_helper_make_dataclass_base_dataclass(self): + @dataclass + class Base1: + x: int + class Base2: + pass + C = make_dataclass('C', + [('y', int)], + bases=(Base1, Base2)) + with self.assertRaisesRegex(TypeError, 'required positional'): + c = C(2) + c = C(1, 2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + self.assertEqual((c.x, c.y), (1, 2)) + + def test_helper_make_dataclass_init_var(self): + def post_init(self, y): + self.x *= y + + C = make_dataclass('C', + [('x', int), + ('y', InitVar[int]), + ], + namespace={'__post_init__': post_init}, + ) + c = C(2, 3) + self.assertEqual(vars(c), {'x': 6}) + self.assertEqual(len(fields(c)), 1) + + def test_helper_make_dataclass_class_var(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ]) + c = C(1) + self.assertEqual(vars(c), {'x': 1}) + self.assertEqual(len(fields(c)), 1) + self.assertEqual(C.y, 10) + self.assertEqual(C.z, 20) + + +class TestDocString(unittest.TestCase): + def assertDocStrEqual(self, a, b): + # Because 3.6 and 3.7 differ in how inspect.signature work + # (see bpo #32108), for the time being just compare them with + # whitespace stripped. + self.assertEqual(a.replace(' ', ''), b.replace(' ', '')) + + def test_existing_docstring_not_overridden(self): + @dataclass + class C: + """Lorem ipsum""" + x: int + + self.assertEqual(C.__doc__, "Lorem ipsum") + + def test_docstring_no_fields(self): + @dataclass + class C: + pass + + self.assertDocStrEqual(C.__doc__, "C()") + + def test_docstring_one_field(self): + @dataclass + class C: + x: int + + self.assertDocStrEqual(C.__doc__, "C(x:int)") + + def test_docstring_two_fields(self): + @dataclass + class C: + x: int + y: int + + self.assertDocStrEqual(C.__doc__, "C(x:int, y:int)") + + def test_docstring_three_fields(self): + @dataclass + class C: + x: int + y: int + z: str + + self.assertDocStrEqual(C.__doc__, "C(x:int, y:int, z:str)") + + def test_docstring_one_field_with_default(self): + @dataclass + class C: + x: int = 3 + + self.assertDocStrEqual(C.__doc__, "C(x:int=3)") + + def test_docstring_one_field_with_default_none(self): + @dataclass + class C: + x: Union[int, type(None)] = None + + self.assertDocStrEqual(C.__doc__, "C(x:Union[int, NoneType]=None)") + + def test_docstring_list_field(self): + @dataclass + class C: + x: List[int] + + self.assertDocStrEqual(C.__doc__, "C(x:List[int])") + + def test_docstring_list_field_with_default_factory(self): + @dataclass + class C: + x: List[int] = field(default_factory=list) + + self.assertDocStrEqual(C.__doc__, "C(x:List[int]=)") + + def test_docstring_deque_field(self): + @dataclass + class C: + x: deque + + self.assertDocStrEqual(C.__doc__, "C(x:collections.deque)") + + def test_docstring_deque_field_with_default_factory(self): + @dataclass + class C: + x: deque = field(default_factory=deque) + + self.assertDocStrEqual(C.__doc__, "C(x:collections.deque=)") + + +if __name__ == '__main__': + unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-12-04-15-51-57.bpo-32214.uozdNj.rst b/Misc/NEWS.d/next/Library/2017-12-04-15-51-57.bpo-32214.uozdNj.rst new file mode 100644 index 00000000000..fd9c4d4eed8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-04-15-51-57.bpo-32214.uozdNj.rst @@ -0,0 +1,2 @@ +PEP 557, Data Classes. Provides a decorator which adds boilerplate methods +to classes which use type annotations so specify fields. From webhook-mailer at python.org Mon Dec 4 17:02:36 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 04 Dec 2017 22:02:36 -0000 Subject: [Python-checkins] bpo-32207: Improve tk event exception tracebacks in IDLE. (GH-4703) (#4705) Message-ID: https://github.com/python/cpython/commit/9da33c82124f27eb58ba4cf145675fe7a1035744 commit: 9da33c82124f27eb58ba4cf145675fe7a1035744 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2017-12-04T17:02:32-05:00 summary: bpo-32207: Improve tk event exception tracebacks in IDLE. (GH-4703) (#4705) When tk event handling is driven by IDLE's run loop, a confusing and distracting queue.EMPTY traceback context is no longer added to tk event exception tracebacks. The traceback is now the same as when event handling is driven by user code. Patch based on a suggestion by Serhiy Storchaka. (cherry picked from commit 1e2fcac4972530aa2c963d7e4011021df5ba866e) files: A Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst M Lib/idlelib/run.py diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 6440e673bf5..176fe3db743 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -134,13 +134,17 @@ def main(del_exitfunc=False): # exiting but got an extra KBI? Try again! continue try: - seq, request = rpc.request_queue.get(block=True, timeout=0.05) + request = rpc.request_queue.get(block=True, timeout=0.05) except queue.Empty: + request = None + # Issue 32207: calling handle_tk_events here adds spurious + # queue.Empty traceback to event handling exceptions. + if request: + seq, (method, args, kwargs) = request + ret = method(*args, **kwargs) + rpc.response_queue.put((seq, ret)) + else: handle_tk_events() - continue - method, args, kwargs = request - ret = method(*args, **kwargs) - rpc.response_queue.put((seq, ret)) except KeyboardInterrupt: if quitting: exit_now = True diff --git a/Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst b/Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst new file mode 100644 index 00000000000..e521c9b0bbd --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2017-12-04-15-04-43.bpo-32207.IzyAJo.rst @@ -0,0 +1,6 @@ +Improve tk event exception tracebacks in IDLE. +When tk event handling is driven by IDLE's run loop, a confusing +and distracting queue.EMPTY traceback context is no longer added +to tk event exception tracebacks. The traceback is now the same +as when event handling is driven by user code. Patch based on a +suggestion by Serhiy Storchaka. From webhook-mailer at python.org Mon Dec 4 17:04:19 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 04 Dec 2017 22:04:19 -0000 Subject: [Python-checkins] bpo-30928: update idlelib/NEWS.txt. (#4706) Message-ID: https://github.com/python/cpython/commit/2c0c68d927bfa557f98bac26644f5b64c4b135a7 commit: 2c0c68d927bfa557f98bac26644f5b64c4b135a7 branch: master author: Terry Jan Reedy committer: GitHub date: 2017-12-04T17:04:15-05:00 summary: bpo-30928: update idlelib/NEWS.txt. (#4706) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 71b7976ab8a..be68adf6670 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,13 @@ Released on 2018-06-18? ======================== +bpo-32207: Improve tk event exception tracebacks in IDLE. +When tk event handling is driven by IDLE's run loop, a confusing +and distracting queue.EMPTY traceback context is no longer added +to tk event exception tracebacks. The traceback is now the same +as when event handling is driven by user code. Patch based on +a suggestion by Serhiy Storchaka. + bpo-32164: Delete unused file idlelib/tabbedpages.py. Use of TabbedPageSet in configdialog was replaced by ttk.Notebook. From lp_benchmark_robot at intel.com Mon Dec 4 20:37:13 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Mon, 4 Dec 2017 17:37:13 -0800 Subject: [Python-checkins] [1 down, 64 flat] Results for Python (master branch) 2017-12-04 Message-ID: Results for project python/master, build date: 2017-12-04 03:03:04-08:00. - commit: e69fbb6 - previous commit: bf2b65e - revision date: 2017-12-04 11:51:55+02:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.932% | -0.711% | +4.982% | +8.402% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.961% | -1.058% | +22.144% | +13.101% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.162% | -0.302% | +23.224% | +12.051% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.177% | -0.753% | +20.981% | +11.466% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.658% | -1.837% | +7.531% | +6.021% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 0.997% | -0.045% | +9.703% | +11.588% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.493% | +0.166% | +7.191% | +10.210% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.461% | -0.197% | +0.456% | +9.069% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.594% | +2.289% | +8.095% | +19.105% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.865% | +0.237% | +12.046% | +13.030% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.561% | -0.840% | +3.523% | +7.839% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 1.236% | -0.711% | +4.950% | +6.910% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.000% | -0.392% | +2.813% | +7.407% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.173% | -0.969% | +13.421% | +9.505% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 2.230% | -0.375% | +8.892% | +9.887% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.819% | -0.478% | +5.481% | +12.836% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.404% | -0.235% | +10.600% | +11.959% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.784% | -0.839% | +8.254% | +9.249% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.015% | -0.371% | +2.951% | +8.839% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.833% | +0.081% | +0.720% | +11.298% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.660% | +0.256% | +6.505% | +12.705% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.410% | -0.073% | +47.147% | +11.850% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.442% | -0.726% | +6.902% | +14.280% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.541% | -0.423% | +16.910% | +13.454% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.534% | -0.709% | +6.865% | +11.176% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.335% | +0.168% | +3.516% | +6.078% | +-----+------------------------+--------+------------+------------+------------+ | :-( | nbody| 0.760% | -2.653% | -2.416% | +2.836% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.664% | -0.109% | +4.655% | +9.166% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.363% | +0.376% | +6.016% | +10.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.768% | +0.800% | +1.659% | +19.566% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.939% | -0.194% | +1.154% | +19.555% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.798% | +0.544% | +3.128% | +20.462% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 2.094% | +0.031% | +12.023% | +10.047% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.343% | -0.092% | +0.067% | +10.367% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.140% | +0.025% | +10.582% | +5.450% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.117% | -0.139% | +1.789% | +5.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.135% | -0.975% | +8.961% | +14.644% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.419% | -0.324% | +0.353% | +11.534% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.373% | +0.008% | -1.319% | +11.278% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 3.294% | -2.678% | -5.526% | +9.275% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.558% | +2.264% | +7.434% | +5.737% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.635% | -0.067% | +8.143% | +14.503% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.439% | -0.057% | -2.036% | +4.762% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.290% | -0.167% | +28.116% | +6.334% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.208% | -1.183% | +4.173% | +6.369% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.258% | -0.799% | +13.337% | +10.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.733% | -1.185% | -3.380% | +3.494% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.687% | -0.085% | +4.044% | +3.914% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.144% | +0.035% | +6.332% | +7.258% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.470% | +0.642% | +6.939% | +3.773% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 5.716% | -1.893% | +16.599% | +10.810% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.653% | -0.696% | +10.880% | +7.970% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.607% | -0.319% | +8.731% | +6.648% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.208% | -0.706% | +10.510% | +9.204% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.357% | -1.721% | +10.031% | +10.714% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 5.104% | -4.945% | +20.032% | +12.502% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.064% | +0.808% | +6.121% | +6.104% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.761% | +0.462% | +2.735% | +0.364% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.602% | -4.614% | +4.311% | +21.977% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.353% | +1.685% | -1.291% | +20.302% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.097% | -0.575% | +6.427% | +7.089% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.129% | -0.572% | +5.405% | +9.143% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.488% | +0.910% | +4.009% | +6.285% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.778% | +1.095% | -6.214% | +11.761% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.327% | -0.627% | +6.545% | +9.560% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-down-64-flat-results-for-python-master-branch-2017-12-04 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Mon Dec 4 21:04:52 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 02:04:52 -0000 Subject: [Python-checkins] bpo-28791: Update macOS installer to use SQLite 3.21.0. (#4245) Message-ID: https://github.com/python/cpython/commit/ca7562a7fea61646c1b40ace04deecf9903d34a1 commit: ca7562a7fea61646c1b40ace04deecf9903d34a1 branch: master author: Mariatta committer: Ned Deily date: 2017-12-04T21:04:49-05:00 summary: bpo-28791: Update macOS installer to use SQLite 3.21.0. (#4245) files: A Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 4cb7e3214cd..3b8cf69d757 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -315,9 +315,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.14.2", - url="https://www.sqlite.org/2016/sqlite-autoconf-3140200.tar.gz", - checksum='90c53cacb811db27f990b8292bd96159', + name="SQLite 3.21.0", + url="https://www.sqlite.org/2017/sqlite-autoconf-3210000.tar.gz", + checksum='7913de4c3126ba3c24689cb7a199ea31', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst b/Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst new file mode 100644 index 00000000000..ef9bc0f6ccc --- /dev/null +++ b/Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst @@ -0,0 +1 @@ +Update OS X installer to use SQLite 3.21.0. From webhook-mailer at python.org Mon Dec 4 21:29:33 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 02:29:33 -0000 Subject: [Python-checkins] [3.6] bpo-28791: Update macOS installer to use SQLite 3.21.0. (#4245) (#4711) Message-ID: https://github.com/python/cpython/commit/a72e7bf563d5a9fb706a1775f5ae883a91b8a99f commit: a72e7bf563d5a9fb706a1775f5ae883a91b8a99f branch: 3.6 author: Ned Deily committer: GitHub date: 2017-12-04T21:29:30-05:00 summary: [3.6] bpo-28791: Update macOS installer to use SQLite 3.21.0. (#4245) (#4711) files: A Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 4cb7e3214cd..3b8cf69d757 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -315,9 +315,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.14.2", - url="https://www.sqlite.org/2016/sqlite-autoconf-3140200.tar.gz", - checksum='90c53cacb811db27f990b8292bd96159', + name="SQLite 3.21.0", + url="https://www.sqlite.org/2017/sqlite-autoconf-3210000.tar.gz", + checksum='7913de4c3126ba3c24689cb7a199ea31', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst b/Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst new file mode 100644 index 00000000000..ef9bc0f6ccc --- /dev/null +++ b/Misc/NEWS.d/next/Build/2017-11-02-20-13-46.bpo-28791.STt3jL.rst @@ -0,0 +1 @@ +Update OS X installer to use SQLite 3.21.0. From webhook-mailer at python.org Mon Dec 4 21:44:00 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 02:44:00 -0000 Subject: [Python-checkins] [bpo-28556] Minor fixes for typing module (#4710) Message-ID: https://github.com/python/cpython/commit/29bc19321018ec6e58f9f4da9c18c42e9a9c580e commit: 29bc19321018ec6e58f9f4da9c18c42e9a9c580e branch: master author: Ivan Levkivskyi committer: Ned Deily date: 2017-12-04T21:43:58-05:00 summary: [bpo-28556] Minor fixes for typing module (#4710) files: A Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index a3b6eb93393..4ae1ebf05f3 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -37,6 +37,9 @@ from test import mod_generics_cache +PY36 = sys.version_info[:2] >= (3, 6) + + class BaseTestCase(TestCase): def assertIsSubclass(self, cls, class_or_tuple, msg=None): @@ -633,6 +636,27 @@ def test_init(self): with self.assertRaises(TypeError): Generic[T, S, T] + @skipUnless(PY36, "__init_subclass__ support required") + def test_init_subclass(self): + class X(typing.Generic[T]): + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.attr = 42 + class Y(X): + pass + self.assertEqual(Y.attr, 42) + with self.assertRaises(AttributeError): + X.attr + X.attr = 1 + Y.attr = 2 + class Z(Y): + pass + class W(X[int]): + pass + self.assertEqual(Y.attr, 2) + self.assertEqual(Z.attr, 42) + self.assertEqual(W.attr, 42) + def test_repr(self): self.assertEqual(repr(SimpleMapping), __name__ + '.' + 'SimpleMapping') @@ -1080,6 +1104,30 @@ class Node(Generic[T]): ... self.assertTrue(t is copy(t)) self.assertTrue(t is deepcopy(t)) + def test_copy_generic_instances(self): + T = TypeVar('T') + class C(Generic[T]): + def __init__(self, attr: T) -> None: + self.attr = attr + + c = C(42) + self.assertEqual(copy(c).attr, 42) + self.assertEqual(deepcopy(c).attr, 42) + self.assertIsNot(copy(c), c) + self.assertIsNot(deepcopy(c), c) + c.attr = 1 + self.assertEqual(copy(c).attr, 1) + self.assertEqual(deepcopy(c).attr, 1) + ci = C[int](42) + self.assertEqual(copy(ci).attr, 42) + self.assertEqual(deepcopy(ci).attr, 42) + self.assertIsNot(copy(ci), ci) + self.assertIsNot(deepcopy(ci), ci) + ci.attr = 1 + self.assertEqual(copy(ci).attr, 1) + self.assertEqual(deepcopy(ci).attr, 1) + self.assertEqual(ci.__orig_class__, C[int]) + def test_weakref_all(self): T = TypeVar('T') things = [Any, Union[T, int], Callable[..., T], Tuple[Any, Any], @@ -1580,8 +1628,6 @@ class ACM: asyncio = None AwaitableWrapper = AsyncIteratorWrapper = ACM = object -PY36 = sys.version_info[:2] >= (3, 6) - PY36_TESTS = """ from test import ann_module, ann_module2, ann_module3 from typing import AsyncContextManager diff --git a/Lib/typing.py b/Lib/typing.py index c00a3a10e1f..b5564cc29a2 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -973,7 +973,8 @@ def __new__(cls, name, bases, namespace, # remove bare Generic from bases if there are other generic bases if any(isinstance(b, GenericMeta) and b is not Generic for b in bases): bases = tuple(b for b in bases if b is not Generic) - namespace.update({'__origin__': origin, '__extra__': extra}) + namespace.update({'__origin__': origin, '__extra__': extra, + '_gorg': None if not origin else origin._gorg}) self = super().__new__(cls, name, bases, namespace, _root=True) super(GenericMeta, self).__setattr__('_gorg', self if not origin else origin._gorg) @@ -1160,17 +1161,12 @@ def __instancecheck__(self, instance): # classes are supposed to be rare anyways. return issubclass(instance.__class__, self) - def __copy__(self): - return self.__class__(self.__name__, self.__bases__, - _no_slots_copy(self.__dict__), - self.__parameters__, self.__args__, self.__origin__, - self.__extra__, self.__orig_bases__) - def __setattr__(self, attr, value): # We consider all the subscripted generics as proxies for original class if ( attr.startswith('__') and attr.endswith('__') or - attr.startswith('_abc_') + attr.startswith('_abc_') or + self._gorg is None # The class is not fully created, see #typing/506 ): super(GenericMeta, self).__setattr__(attr, value) else: diff --git a/Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst b/Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst new file mode 100644 index 00000000000..8f3a8954970 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst @@ -0,0 +1,3 @@ +Two minor fixes for ``typing`` module: allow shallow copying instances of +generic classes, improve interaction of ``__init_subclass__`` with generics. +Original PRs by Ivan Levkivskyi. From webhook-mailer at python.org Mon Dec 4 21:50:32 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 02:50:32 -0000 Subject: [Python-checkins] Enable SQLite JSON functions for macOS installer build (#4712) Message-ID: https://github.com/python/cpython/commit/9625bf520e08828e36bc3b1d043af679eb5f993d commit: 9625bf520e08828e36bc3b1d043af679eb5f993d branch: master author: Ned Deily committer: GitHub date: 2017-12-04T21:50:29-05:00 summary: Enable SQLite JSON functions for macOS installer build (#4712) files: M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 3b8cf69d757..674f025db3e 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -322,6 +322,7 @@ def library_recipes(): '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' '-DSQLITE_ENABLE_FTS3_PARENTHESIS ' + '-DSQLITE_ENABLE_JSON1 ' '-DSQLITE_ENABLE_RTREE ' '-DSQLITE_TCL=0 ' '%s' % ('','-DSQLITE_WITHOUT_ZONEMALLOC ')[LT_10_5]), From webhook-mailer at python.org Mon Dec 4 21:58:15 2017 From: webhook-mailer at python.org (Neil Schemenauer) Date: Tue, 05 Dec 2017 02:58:15 -0000 Subject: [Python-checkins] bpo-19610: Warn if distutils is provided something other than a list to some fields (#4685) Message-ID: https://github.com/python/cpython/commit/8837dd092fe5ad5184889104e8036811ed839f98 commit: 8837dd092fe5ad5184889104e8036811ed839f98 branch: master author: Neil Schemenauer committer: GitHub date: 2017-12-04T18:58:12-08:00 summary: bpo-19610: Warn if distutils is provided something other than a list to some fields (#4685) * Rather than raise TypeError, warn and call list() on the value. * Fix tests, revise NEWS and whatsnew text. * Revise documentation, a string is okay as well. * Ensure 'requires' and 'obsoletes' are real lists. * Test that requires and obsoletes are turned to lists. files: M Doc/distutils/apiref.rst M Doc/whatsnew/3.7.rst M Lib/distutils/dist.py M Lib/distutils/tests/test_dist.py M Misc/NEWS.d/next/Library/2017-11-23-16-15-55.bpo-19610.Dlca2P.rst diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index ced8837d373..9fce46ad266 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -286,9 +286,9 @@ the full reference. Distribution constructor. :func:`setup` creates a Distribution instance. .. versionchanged:: 3.7 - :class:`~distutils.core.Distribution` now raises a :exc:`TypeError` if - ``classifiers``, ``keywords`` and ``platforms`` fields are not specified - as a list. + :class:`~distutils.core.Distribution` now warns if ``classifiers``, + ``keywords`` and ``platforms`` fields are not specified as a list or + a string. .. class:: Command diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 3d23aa773d7..9363730bf1f 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -298,10 +298,8 @@ README.rst is now included in the list of distutils standard READMEs and therefore included in source distributions. (Contributed by Ryan Gonzalez in :issue:`11913`.) -:class:`distutils.core.setup` now raises a :exc:`TypeError` if -``classifiers``, ``keywords`` and ``platforms`` fields are not specified -as a list. However, to minimize backwards incompatibility concerns, -``keywords`` and ``platforms`` fields still accept a comma separated string. +:class:`distutils.core.setup` now warns if the ``classifiers``, ``keywords`` +and ``platforms`` fields are not specified as a list or a string. (Contributed by Berker Peksag in :issue:`19610`.) http.client diff --git a/Lib/distutils/dist.py b/Lib/distutils/dist.py index 78c29ede6c2..6cf0a0d6632 100644 --- a/Lib/distutils/dist.py +++ b/Lib/distutils/dist.py @@ -27,6 +27,20 @@ command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$') +def _ensure_list(value, fieldname): + if isinstance(value, str): + # a string containing comma separated values is okay. It will + # be converted to a list by Distribution.finalize_options(). + pass + elif not isinstance(value, list): + # passing a tuple or an iterator perhaps, warn and convert + typename = type(value).__name__ + msg = f"Warning: '{fieldname}' should be a list, got type '{typename}'" + log.log(log.WARN, msg) + value = list(value) + return value + + class Distribution: """The core of the Distutils. Most of the work hiding behind 'setup' is really done within a Distribution instance, which farms the work out @@ -257,10 +271,7 @@ def __init__(self, attrs=None): setattr(self, key, val) else: msg = "Unknown distribution option: %s" % repr(key) - if warnings is not None: - warnings.warn(msg) - else: - sys.stderr.write(msg + "\n") + warnings.warn(msg) # no-user-cfg is handled before other command line args # because other args override the config files, and this @@ -1189,36 +1200,19 @@ def get_keywords(self): return self.keywords or [] def set_keywords(self, value): - # If 'keywords' is a string, it will be converted to a list - # by Distribution.finalize_options(). To maintain backwards - # compatibility, do not raise an exception if 'keywords' is - # a string. - if not isinstance(value, (list, str)): - msg = "'keywords' should be a 'list', not %r" - raise TypeError(msg % type(value).__name__) - self.keywords = value + self.keywords = _ensure_list(value, 'keywords') def get_platforms(self): return self.platforms or ["UNKNOWN"] def set_platforms(self, value): - # If 'platforms' is a string, it will be converted to a list - # by Distribution.finalize_options(). To maintain backwards - # compatibility, do not raise an exception if 'platforms' is - # a string. - if not isinstance(value, (list, str)): - msg = "'platforms' should be a 'list', not %r" - raise TypeError(msg % type(value).__name__) - self.platforms = value + self.platforms = _ensure_list(value, 'platforms') def get_classifiers(self): return self.classifiers or [] def set_classifiers(self, value): - if not isinstance(value, list): - msg = "'classifiers' should be a 'list', not %r" - raise TypeError(msg % type(value).__name__) - self.classifiers = value + self.classifiers = _ensure_list(value, 'classifiers') def get_download_url(self): return self.download_url or "UNKNOWN" @@ -1231,7 +1225,7 @@ def set_requires(self, value): import distutils.versionpredicate for v in value: distutils.versionpredicate.VersionPredicate(v) - self.requires = value + self.requires = list(value) def get_provides(self): return self.provides or [] @@ -1250,7 +1244,7 @@ def set_obsoletes(self, value): import distutils.versionpredicate for v in value: distutils.versionpredicate.VersionPredicate(v) - self.obsoletes = value + self.obsoletes = list(value) def fix_help_options(options): """Convert a 4-tuple 'help_options' list as found in various command diff --git a/Lib/distutils/tests/test_dist.py b/Lib/distutils/tests/test_dist.py index 50b456ec947..0a19f0fb627 100644 --- a/Lib/distutils/tests/test_dist.py +++ b/Lib/distutils/tests/test_dist.py @@ -11,7 +11,9 @@ from distutils.dist import Distribution, fix_help_options, DistributionMetadata from distutils.cmd import Command -from test.support import TESTFN, captured_stdout, run_unittest +from test.support import ( + TESTFN, captured_stdout, captured_stderr, run_unittest +) from distutils.tests import support from distutils import log @@ -319,6 +321,13 @@ def test_requires_illegal(self): "version": "1.0", "requires": ["my.pkg (splat)"]}) + def test_requires_to_list(self): + attrs = {"name": "package", + "requires": iter(["other"])} + dist = Distribution(attrs) + self.assertIsInstance(dist.metadata.requires, list) + + def test_obsoletes(self): attrs = {"name": "package", "version": "1.0", @@ -341,6 +350,12 @@ def test_obsoletes_illegal(self): "version": "1.0", "obsoletes": ["my.pkg (splat)"]}) + def test_obsoletes_to_list(self): + attrs = {"name": "package", + "obsoletes": iter(["other"])} + dist = Distribution(attrs) + self.assertIsInstance(dist.metadata.obsoletes, list) + def test_classifier(self): attrs = {'name': 'Boa', 'version': '3.0', 'classifiers': ['Programming Language :: Python :: 3']} @@ -353,9 +368,14 @@ def test_classifier(self): def test_classifier_invalid_type(self): attrs = {'name': 'Boa', 'version': '3.0', 'classifiers': ('Programming Language :: Python :: 3',)} - msg = "'classifiers' should be a 'list', not 'tuple'" - with self.assertRaises(TypeError, msg=msg): - Distribution(attrs) + with captured_stderr() as error: + d = Distribution(attrs) + # should have warning about passing a non-list + self.assertIn('should be a list', error.getvalue()) + # should be converted to a list + self.assertIsInstance(d.metadata.classifiers, list) + self.assertEqual(d.metadata.classifiers, + list(attrs['classifiers'])) def test_keywords(self): attrs = {'name': 'Monty', 'version': '1.0', @@ -367,9 +387,13 @@ def test_keywords(self): def test_keywords_invalid_type(self): attrs = {'name': 'Monty', 'version': '1.0', 'keywords': ('spam', 'eggs', 'life of brian')} - msg = "'keywords' should be a 'list', not 'tuple'" - with self.assertRaises(TypeError, msg=msg): - Distribution(attrs) + with captured_stderr() as error: + d = Distribution(attrs) + # should have warning about passing a non-list + self.assertIn('should be a list', error.getvalue()) + # should be converted to a list + self.assertIsInstance(d.metadata.keywords, list) + self.assertEqual(d.metadata.keywords, list(attrs['keywords'])) def test_platforms(self): attrs = {'name': 'Monty', 'version': '1.0', @@ -381,9 +405,13 @@ def test_platforms(self): def test_platforms_invalid_types(self): attrs = {'name': 'Monty', 'version': '1.0', 'platforms': ('GNU/Linux', 'Some Evil Platform')} - msg = "'platforms' should be a 'list', not 'tuple'" - with self.assertRaises(TypeError, msg=msg): - Distribution(attrs) + with captured_stderr() as error: + d = Distribution(attrs) + # should have warning about passing a non-list + self.assertIn('should be a list', error.getvalue()) + # should be converted to a list + self.assertIsInstance(d.metadata.platforms, list) + self.assertEqual(d.metadata.platforms, list(attrs['platforms'])) def test_download_url(self): attrs = {'name': 'Boa', 'version': '3.0', diff --git a/Misc/NEWS.d/next/Library/2017-11-23-16-15-55.bpo-19610.Dlca2P.rst b/Misc/NEWS.d/next/Library/2017-11-23-16-15-55.bpo-19610.Dlca2P.rst index 5ea87a45722..514740b433f 100644 --- a/Misc/NEWS.d/next/Library/2017-11-23-16-15-55.bpo-19610.Dlca2P.rst +++ b/Misc/NEWS.d/next/Library/2017-11-23-16-15-55.bpo-19610.Dlca2P.rst @@ -1,5 +1,4 @@ -``setup()`` now raises :exc:`TypeError` for invalid types. +``setup()`` now warns about invalid types for some fields. -The ``distutils.dist.Distribution`` class now explicitly raises an exception -when ``classifiers``, ``keywords`` and ``platforms`` fields are not -specified as a list. +The ``distutils.dist.Distribution`` class now warns when ``classifiers``, +``keywords`` and ``platforms`` fields are not specified as a list or a string. From webhook-mailer at python.org Mon Dec 4 22:02:05 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 03:02:05 -0000 Subject: [Python-checkins] [bpo-28556] Minor fixes for typing module (GH-4710) (#4713) Message-ID: https://github.com/python/cpython/commit/b0576278b2d44472c73696f6dea4855f7ffb7ff1 commit: b0576278b2d44472c73696f6dea4855f7ffb7ff1 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2017-12-04T22:02:02-05:00 summary: [bpo-28556] Minor fixes for typing module (GH-4710) (#4713) (cherry picked from commit 29bc19321018ec6e58f9f4da9c18c42e9a9c580e) files: A Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index ffefa8ed2dd..fe5247c2602 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -37,6 +37,9 @@ from test import mod_generics_cache +PY36 = sys.version_info[:2] >= (3, 6) + + class BaseTestCase(TestCase): def assertIsSubclass(self, cls, class_or_tuple, msg=None): @@ -633,6 +636,27 @@ def test_init(self): with self.assertRaises(TypeError): Generic[T, S, T] + @skipUnless(PY36, "__init_subclass__ support required") + def test_init_subclass(self): + class X(typing.Generic[T]): + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.attr = 42 + class Y(X): + pass + self.assertEqual(Y.attr, 42) + with self.assertRaises(AttributeError): + X.attr + X.attr = 1 + Y.attr = 2 + class Z(Y): + pass + class W(X[int]): + pass + self.assertEqual(Y.attr, 2) + self.assertEqual(Z.attr, 42) + self.assertEqual(W.attr, 42) + def test_repr(self): self.assertEqual(repr(SimpleMapping), __name__ + '.' + 'SimpleMapping') @@ -1080,6 +1104,30 @@ class Node(Generic[T]): ... self.assertTrue(t is copy(t)) self.assertTrue(t is deepcopy(t)) + def test_copy_generic_instances(self): + T = TypeVar('T') + class C(Generic[T]): + def __init__(self, attr: T) -> None: + self.attr = attr + + c = C(42) + self.assertEqual(copy(c).attr, 42) + self.assertEqual(deepcopy(c).attr, 42) + self.assertIsNot(copy(c), c) + self.assertIsNot(deepcopy(c), c) + c.attr = 1 + self.assertEqual(copy(c).attr, 1) + self.assertEqual(deepcopy(c).attr, 1) + ci = C[int](42) + self.assertEqual(copy(ci).attr, 42) + self.assertEqual(deepcopy(ci).attr, 42) + self.assertIsNot(copy(ci), ci) + self.assertIsNot(deepcopy(ci), ci) + ci.attr = 1 + self.assertEqual(copy(ci).attr, 1) + self.assertEqual(deepcopy(ci).attr, 1) + self.assertEqual(ci.__orig_class__, C[int]) + def test_weakref_all(self): T = TypeVar('T') things = [Any, Union[T, int], Callable[..., T], Tuple[Any, Any], @@ -1580,8 +1628,6 @@ class ACM: asyncio = None AwaitableWrapper = AsyncIteratorWrapper = ACM = object -PY36 = sys.version_info[:2] >= (3, 6) - PY36_TESTS = """ from test import ann_module, ann_module2, ann_module3 from typing import AsyncContextManager diff --git a/Lib/typing.py b/Lib/typing.py index c00a3a10e1f..b5564cc29a2 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -973,7 +973,8 @@ def __new__(cls, name, bases, namespace, # remove bare Generic from bases if there are other generic bases if any(isinstance(b, GenericMeta) and b is not Generic for b in bases): bases = tuple(b for b in bases if b is not Generic) - namespace.update({'__origin__': origin, '__extra__': extra}) + namespace.update({'__origin__': origin, '__extra__': extra, + '_gorg': None if not origin else origin._gorg}) self = super().__new__(cls, name, bases, namespace, _root=True) super(GenericMeta, self).__setattr__('_gorg', self if not origin else origin._gorg) @@ -1160,17 +1161,12 @@ def __instancecheck__(self, instance): # classes are supposed to be rare anyways. return issubclass(instance.__class__, self) - def __copy__(self): - return self.__class__(self.__name__, self.__bases__, - _no_slots_copy(self.__dict__), - self.__parameters__, self.__args__, self.__origin__, - self.__extra__, self.__orig_bases__) - def __setattr__(self, attr, value): # We consider all the subscripted generics as proxies for original class if ( attr.startswith('__') and attr.endswith('__') or - attr.startswith('_abc_') + attr.startswith('_abc_') or + self._gorg is None # The class is not fully created, see #typing/506 ): super(GenericMeta, self).__setattr__(attr, value) else: diff --git a/Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst b/Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst new file mode 100644 index 00000000000..8f3a8954970 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-05-02-03-07.bpo-28556.9Z_PsJ.rst @@ -0,0 +1,3 @@ +Two minor fixes for ``typing`` module: allow shallow copying instances of +generic classes, improve interaction of ``__init_subclass__`` with generics. +Original PRs by Ivan Levkivskyi. From webhook-mailer at python.org Mon Dec 4 22:24:44 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 03:24:44 -0000 Subject: [Python-checkins] bpo-31392: Update macOS installer to use OpenSSL 1.0.2m (#4715) Message-ID: https://github.com/python/cpython/commit/24e046987b8e34bb4f1f3fd9bd31f1d605e347dc commit: 24e046987b8e34bb4f1f3fd9bd31f1d605e347dc branch: master author: Ned Deily committer: GitHub date: 2017-12-04T22:24:41-05:00 summary: bpo-31392: Update macOS installer to use OpenSSL 1.0.2m (#4715) files: A Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 674f025db3e..dbe5ffd104b 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -213,9 +213,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 1.0.2k", - url="https://www.openssl.org/source/openssl-1.0.2k.tar.gz", - checksum='f965fc0bf01bf882b31314b61391ae65', + name="OpenSSL 1.0.2m", + url="https://www.openssl.org/source/openssl-1.0.2m.tar.gz", + checksum='10e9e37f492094b9ef296f68f24a7666', patches=[ "openssl_sdk_makedepend.patch", ], @@ -845,7 +845,6 @@ def build_openssl_arch(archbase, arch): "enable-tlsext", "no-ssl2", "no-ssl3", - "no-ssl3-method", # "enable-unit-test", "shared", "--install_prefix=%s"%shellQuote(archbase), diff --git a/Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst b/Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst new file mode 100644 index 00000000000..555b3812c6a --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst @@ -0,0 +1 @@ +Update macOS installer to use OpenSSL 1.0.2m From webhook-mailer at python.org Mon Dec 4 22:54:47 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 03:54:47 -0000 Subject: [Python-checkins] [3.6] bpo-31392: Update macOS installer to use OpenSSL 1.0.2m (GH-4715) (#4716) Message-ID: https://github.com/python/cpython/commit/0bec5e147a6c0f62517df8e7033a38087451d5d4 commit: 0bec5e147a6c0f62517df8e7033a38087451d5d4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2017-12-04T22:54:43-05:00 summary: [3.6] bpo-31392: Update macOS installer to use OpenSSL 1.0.2m (GH-4715) (#4716) (cherry picked from commit 24e046987b8e34bb4f1f3fd9bd31f1d605e347dc) files: A Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 3b8cf69d757..52f391a4316 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -213,9 +213,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 1.0.2k", - url="https://www.openssl.org/source/openssl-1.0.2k.tar.gz", - checksum='f965fc0bf01bf882b31314b61391ae65', + name="OpenSSL 1.0.2m", + url="https://www.openssl.org/source/openssl-1.0.2m.tar.gz", + checksum='10e9e37f492094b9ef296f68f24a7666', patches=[ "openssl_sdk_makedepend.patch", ], @@ -844,7 +844,6 @@ def build_openssl_arch(archbase, arch): "enable-tlsext", "no-ssl2", "no-ssl3", - "no-ssl3-method", # "enable-unit-test", "shared", "--install_prefix=%s"%shellQuote(archbase), diff --git a/Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst b/Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst new file mode 100644 index 00000000000..555b3812c6a --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2017-12-04-21-57-43.bpo-31392.f8huBC.rst @@ -0,0 +1 @@ +Update macOS installer to use OpenSSL 1.0.2m From webhook-mailer at python.org Mon Dec 4 22:55:22 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 03:55:22 -0000 Subject: [Python-checkins] Update macOS installer to XZ 5.2.3 (#4718) Message-ID: https://github.com/python/cpython/commit/e6f8a7378d701823c6821217bf7ac8a540ab143b commit: e6f8a7378d701823c6821217bf7ac8a540ab143b branch: master author: Ned Deily committer: GitHub date: 2017-12-04T22:55:20-05:00 summary: Update macOS installer to XZ 5.2.3 (#4718) files: M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index dbe5ffd104b..cc6241f817a 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -270,9 +270,9 @@ def library_recipes(): if PYTHON_3: result.extend([ dict( - name="XZ 5.2.2", - url="http://tukaani.org/xz/xz-5.2.2.tar.gz", - checksum='7cf6a8544a7dae8e8106fdf7addfa28c', + name="XZ 5.2.3", + url="http://tukaani.org/xz/xz-5.2.3.tar.gz", + checksum='ef68674fb47a8b8e741b34e429d86e9d', configure_pre=[ '--disable-dependency-tracking', ] From webhook-mailer at python.org Mon Dec 4 23:10:00 2017 From: webhook-mailer at python.org (Mariatta) Date: Tue, 05 Dec 2017 04:10:00 -0000 Subject: [Python-checkins] bpo-28791: Update Windows builds to use SQLite 3.21.0. (GH-4246). (GH-4717) Message-ID: https://github.com/python/cpython/commit/e2ba5523192a9cff125fce2ce530bec574353f7b commit: e2ba5523192a9cff125fce2ce530bec574353f7b branch: 3.6 author: Mariatta committer: GitHub date: 2017-12-04T20:09:57-08:00 summary: bpo-28791: Update Windows builds to use SQLite 3.21.0. (GH-4246). (GH-4717) (cherry picked from commit 31af650ee25f65794b75d4dfefed6fe4758781c1) files: A Misc/NEWS.d/next/Build/2017-11-02-20-30-57.bpo-28791.VaE3o8.rst M PCbuild/get_externals.bat M PCbuild/python.props M PCbuild/readme.txt diff --git a/Misc/NEWS.d/next/Build/2017-11-02-20-30-57.bpo-28791.VaE3o8.rst b/Misc/NEWS.d/next/Build/2017-11-02-20-30-57.bpo-28791.VaE3o8.rst new file mode 100644 index 00000000000..b25b0e0e9f3 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2017-11-02-20-30-57.bpo-28791.VaE3o8.rst @@ -0,0 +1 @@ +Update Windows builds to use SQLite 3.21.0. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 0a86892c350..e6faab14de7 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -42,7 +42,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeSSL%"=="false" set libraries=%libraries% openssl-1.0.2k -set libraries=%libraries% sqlite-3.14.2.0 +set libraries=%libraries% sqlite-3.21.0.0 if NOT "%IncludeTkinter%"=="false" set libraries=%libraries% tcl-core-8.6.6.0 if NOT "%IncludeTkinter%"=="false" set libraries=%libraries% tk-8.6.6.0 if NOT "%IncludeTkinter%"=="false" set libraries=%libraries% tix-8.4.3.6 diff --git a/PCbuild/python.props b/PCbuild/python.props index 82cb8b646fe..16a7672315f 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -44,7 +44,7 @@ $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals\`)) - $(ExternalsDir)sqlite-3.14.2.0\ + $(ExternalsDir)sqlite-3.21.0.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ $(ExternalsDir)openssl-1.0.2k\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index d4fd9a567cc..6f9b9a215c4 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -212,7 +212,7 @@ _ssl functionality to _ssl or _hashlib. They will not clean up their output with the normal Clean target; CleanAll should be used instead. _sqlite3 - Wraps SQLite 3.14.2.0, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.21.0.0, which is itself built by sqlite3.vcxproj Homepage: http://www.sqlite.org/ _tkinter From webhook-mailer at python.org Mon Dec 4 23:42:05 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 04:42:05 -0000 Subject: [Python-checkins] bpo-31380: Skip test_httpservers test_undecodable_file on macOS. (#4720) Message-ID: https://github.com/python/cpython/commit/b3edde8dd44c878e9f039a2165d00ff075157d4b commit: b3edde8dd44c878e9f039a2165d00ff075157d4b branch: master author: Ned Deily committer: GitHub date: 2017-12-04T23:42:02-05:00 summary: bpo-31380: Skip test_httpservers test_undecodable_file on macOS. (#4720) The undecodable file name cannot be created on macOS APFS file systems. files: A Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst M Lib/test/test_httpservers.py diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 20e6f66766f..cc829a522b8 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -384,7 +384,8 @@ def close_conn(): reader.close() return body - @support.requires_mac_ver(10, 5) + @unittest.skipIf(sys.platform == 'darwin', + 'undecodable name cannot always be decoded on macOS') @unittest.skipIf(sys.platform == 'win32', 'undecodable name cannot be decoded on win32') @unittest.skipUnless(support.TESTFN_UNDECODABLE, diff --git a/Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst b/Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst new file mode 100644 index 00000000000..2baecf5adcf --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst @@ -0,0 +1 @@ +Skip test_httpservers test_undecodable_file on macOS: fails on APFS. From webhook-mailer at python.org Tue Dec 5 00:03:32 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 05:03:32 -0000 Subject: [Python-checkins] [3.6] bpo-31380: Skip test_httpservers test_undecodable_file on macOS. (GH-4720) (#4721) Message-ID: https://github.com/python/cpython/commit/d9cadc5f597e5966132c9249f6c7ff0ed1eba0cb commit: d9cadc5f597e5966132c9249f6c7ff0ed1eba0cb branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2017-12-05T00:03:29-05:00 summary: [3.6] bpo-31380: Skip test_httpservers test_undecodable_file on macOS. (GH-4720) (#4721) The undecodable file name cannot be created on macOS APFS file systems. (cherry picked from commit b3edde8dd44c878e9f039a2165d00ff075157d4b) files: A Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst M Lib/test/test_httpservers.py diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 22b3bf5235c..66e937e04b6 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -370,7 +370,8 @@ def close_conn(): reader.close() return body - @support.requires_mac_ver(10, 5) + @unittest.skipIf(sys.platform == 'darwin', + 'undecodable name cannot always be decoded on macOS') @unittest.skipIf(sys.platform == 'win32', 'undecodable name cannot be decoded on win32') @unittest.skipUnless(support.TESTFN_UNDECODABLE, diff --git a/Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst b/Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst new file mode 100644 index 00000000000..2baecf5adcf --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-12-04-23-19-16.bpo-31380.VlMmHW.rst @@ -0,0 +1 @@ +Skip test_httpservers test_undecodable_file on macOS: fails on APFS. From webhook-mailer at python.org Tue Dec 5 00:05:36 2017 From: webhook-mailer at python.org (Mariatta) Date: Tue, 05 Dec 2017 05:05:36 -0000 Subject: [Python-checkins] Add a missing space in tkinter documentation. (GH-4692) Message-ID: https://github.com/python/cpython/commit/ae342cf7deebdcf2035f4064609b32b2102dadcf commit: ae342cf7deebdcf2035f4064609b32b2102dadcf branch: master author: Julien Palard committer: Mariatta date: 2017-12-04T21:05:33-08:00 summary: Add a missing space in tkinter documentation. (GH-4692) files: M Doc/library/tkinter.rst diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 3e1faed8c7b..f51add2b41f 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -154,7 +154,7 @@ background material, while the second half can be taken to the keyboard as a handy reference. When trying to answer questions of the form "how do I do blah", it is often best -to find out how to do"blah" in straight Tk, and then convert this back into the +to find out how to do "blah" in straight Tk, and then convert this back into the corresponding :mod:`tkinter` call. Python programmers can often guess at the correct Python command by looking at the Tk documentation. This means that in order to use Tkinter, you will have to know a little bit about Tk. This document From webhook-mailer at python.org Tue Dec 5 00:16:00 2017 From: webhook-mailer at python.org (Mariatta) Date: Tue, 05 Dec 2017 05:16:00 -0000 Subject: [Python-checkins] Add a missing space in tkinter documentation. (GH-4692). (GH-4723) Message-ID: https://github.com/python/cpython/commit/12fa6b1e2ff8112b0a9f61949c3d5252a75bf909 commit: 12fa6b1e2ff8112b0a9f61949c3d5252a75bf909 branch: 2.7 author: Mariatta committer: GitHub date: 2017-12-04T21:15:57-08:00 summary: Add a missing space in tkinter documentation. (GH-4692). (GH-4723) (cherry picked from commit ae342cf7deebdcf2035f4064609b32b2102dadcf) files: M Doc/library/tkinter.rst diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index ab1da524377..ce5e63a717b 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -161,7 +161,7 @@ background material, while the second half can be taken to the keyboard as a handy reference. When trying to answer questions of the form "how do I do blah", it is often best -to find out how to do"blah" in straight Tk, and then convert this back into the +to find out how to do "blah" in straight Tk, and then convert this back into the corresponding :mod:`Tkinter` call. Python programmers can often guess at the correct Python command by looking at the Tk documentation. This means that in order to use Tkinter, you will have to know a little bit about Tk. This document From webhook-mailer at python.org Tue Dec 5 00:16:23 2017 From: webhook-mailer at python.org (Mariatta) Date: Tue, 05 Dec 2017 05:16:23 -0000 Subject: [Python-checkins] Add a missing space in tkinter documentation. (GH-4692) (GH-4722) Message-ID: https://github.com/python/cpython/commit/3b5541670036cc57205fb91f1fc332a952898962 commit: 3b5541670036cc57205fb91f1fc332a952898962 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2017-12-04T21:16:20-08:00 summary: Add a missing space in tkinter documentation. (GH-4692) (GH-4722) (cherry picked from commit ae342cf7deebdcf2035f4064609b32b2102dadcf) files: M Doc/library/tkinter.rst diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 3e1faed8c7b..f51add2b41f 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -154,7 +154,7 @@ background material, while the second half can be taken to the keyboard as a handy reference. When trying to answer questions of the form "how do I do blah", it is often best -to find out how to do"blah" in straight Tk, and then convert this back into the +to find out how to do "blah" in straight Tk, and then convert this back into the corresponding :mod:`tkinter` call. Python programmers can often guess at the correct Python command by looking at the Tk documentation. This means that in order to use Tkinter, you will have to know a little bit about Tk. This document From solipsis at pitrou.net Tue Dec 5 04:19:00 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 05 Dec 2017 09:19:00 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171205091900.10560.84C8760EEEEF17B5@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog1jQDC8', '--timeout', '7200'] From webhook-mailer at python.org Tue Dec 5 09:12:48 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 05 Dec 2017 14:12:48 -0000 Subject: [Python-checkins] bpo-32030: Simplify _PyCoreConfig_INIT macro (#4728) Message-ID: https://github.com/python/cpython/commit/33c377ed9b6cb3b9493005314c4e0cfa7517ea65 commit: 33c377ed9b6cb3b9493005314c4e0cfa7517ea65 branch: master author: Victor Stinner committer: GitHub date: 2017-12-05T15:12:41+01:00 summary: bpo-32030: Simplify _PyCoreConfig_INIT macro (#4728) * Simplify _PyCoreConfig_INIT, _PyMainInterpreterConfig_INIT, _PyPathConfig_INIT macros: no need to set fields to 0/NULL, it's redundant (the C language sets them to 0/NULL for us). * Fix typo: pymain_run_statup() => pymain_run_startup() * Remove a few XXX/TODO files: M Include/internal/pystate.h M Include/pystate.h M Modules/main.c M Python/pylifecycle.c diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index b9334212047..6b527fbe214 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -54,23 +54,8 @@ typedef struct { wchar_t *home; } _PyPathConfig; -#ifdef MS_WINDOWS -#define _PyPathConfig_INIT \ - {.program_full_path = NULL, \ - .prefix = NULL, \ - .dll_path = NULL, \ - .module_search_path = NULL, \ - .program_name = NULL, \ - .home = NULL} -#else -#define _PyPathConfig_INIT \ - {.program_full_path = NULL, \ - .prefix = NULL, \ - .exec_prefix = NULL, \ - .module_search_path = NULL, \ - .program_name = NULL, \ - .home = NULL} -#endif +#define _PyPathConfig_INIT {.module_search_path = NULL} +/* Note: _PyPathConfig_INIT sets other fields to 0/NULL */ PyAPI_DATA(_PyPathConfig) _Py_path_config; @@ -116,6 +101,7 @@ typedef struct pyruntimestate { } _PyRuntimeState; #define _PyRuntimeState_INIT {.initialized = 0, .core_initialized = 0} +/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ PyAPI_DATA(_PyRuntimeState) _PyRuntime; PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *); diff --git a/Include/pystate.h b/Include/pystate.h index 1d8aab6d83f..cf45b059977 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -38,19 +38,8 @@ typedef struct { int show_alloc_count; /* -X showalloccount */ } _PyCoreConfig; -#define _PyCoreConfig_INIT \ - (_PyCoreConfig){\ - .ignore_environment = 0, \ - .use_hash_seed = -1, \ - .hash_seed = 0, \ - ._disable_importlib = 0, \ - .allocator = NULL, \ - .dev_mode = 0, \ - .faulthandler = 0, \ - .tracemalloc = 0, \ - .import_time = 0, \ - .show_ref_count = 0, \ - .show_alloc_count = 0} +#define _PyCoreConfig_INIT (_PyCoreConfig){.use_hash_seed = -1} +/* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ /* Placeholders while working on the new configuration API * @@ -69,11 +58,8 @@ typedef struct { } _PyMainInterpreterConfig; #define _PyMainInterpreterConfig_INIT \ - (_PyMainInterpreterConfig){\ - .install_signal_handlers = -1, \ - .module_search_path_env = NULL, \ - .home = NULL, \ - .program_name = NULL} + (_PyMainInterpreterConfig){.install_signal_handlers = -1} +/* Note: _PyMainInterpreterConfig_INIT sets other fields to 0/NULL */ typedef struct _is { diff --git a/Modules/main.c b/Modules/main.c index 4095259b88c..e2ca72c7dc1 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -160,7 +160,7 @@ pymain_get_env_var(const char *name) static void -pymain_run_statup(PyCompilerFlags *cf) +pymain_run_startup(PyCompilerFlags *cf) { char *startup = Py_GETENV("PYTHONSTARTUP"); if (startup == NULL || startup[0] == '\0') { @@ -367,8 +367,6 @@ pymain_run_file(FILE *fp, const wchar_t *filename, PyCompilerFlags *p_cf) /* Main program */ -/*TODO: Add arg processing to PEP 432 as a new configuration setup API - */ typedef struct { size_t len; wchar_t **options; @@ -949,8 +947,6 @@ pymain_get_program_name(_PyMain *pymain) * * Replaces previous call to Py_Initialize() * - * TODO: Move environment queries (etc) into Py_ReadConfig - * * Return 0 on success. * Set pymain->err and return -1 on error. */ @@ -1121,10 +1117,9 @@ pymain_run_filename(_PyMain *pymain) if (cmdline->filename == NULL && pymain->stdin_is_interactive) { Py_InspectFlag = 0; /* do exit on SystemExit */ - pymain_run_statup(&pymain->cf); + pymain_run_startup(&pymain->cf); pymain_run_interactive_hook(); } - /* XXX */ if (pymain->main_importer_path != NULL) { pymain->status = pymain_run_main_from_importer(pymain); @@ -1162,7 +1157,7 @@ pymain_repl(_PyMain *pymain) Py_InspectFlag = 0; pymain_run_interactive_hook(); - /* XXX */ + int res = PyRun_AnyFileFlags(stdin, "", &pymain->cf); pymain->status = (res != 0); } @@ -1630,7 +1625,6 @@ pymain_init(_PyMain *pymain) } pymain->core_config._disable_importlib = 0; - /* TODO: Moar config options! */ pymain->config.install_signal_handlers = 1; orig_argc = pymain->argc; /* For Py_GetArgcArgv() */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 523397f1269..b615c799989 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -606,10 +606,6 @@ _Py_SetLocaleFromEnv(int category) * safe to call without calling Py_Initialize first) */ -/* TODO: Progressively move functionality from Py_BeginInitialization to - * Py_ReadConfig and Py_EndInitialization - */ - _PyInitError _Py_InitializeCore(const _PyCoreConfig *config) { @@ -881,10 +877,9 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return _Py_INIT_OK(); } - /* TODO: Report exceptions rather than fatal errors below here */ - - if (_PyTime_Init() < 0) + if (_PyTime_Init() < 0) { return _Py_INIT_ERR("can't initialize time"); + } /* GetPath may initialize state that _PySys_EndInit locks in, and so has to be called first. */ From webhook-mailer at python.org Tue Dec 5 13:44:12 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 05 Dec 2017 18:44:12 -0000 Subject: [Python-checkins] bpo-30928: update idlelib/NEWS.txt. (GH-4706) (#4707) Message-ID: https://github.com/python/cpython/commit/7a6f28f2802db3da79b3c2bd5d75e40eb0709744 commit: 7a6f28f2802db3da79b3c2bd5d75e40eb0709744 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2017-12-05T13:44:09-05:00 summary: bpo-30928: update idlelib/NEWS.txt. (GH-4706) (#4707) (cherry picked from commit 2c0c68d927bfa557f98bac26644f5b64c4b135a7) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 6e1f0cc95ca..56d37f3baa4 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,13 @@ Released on 2017-09-25? ======================== +bpo-32207: Improve tk event exception tracebacks in IDLE. +When tk event handling is driven by IDLE's run loop, a confusing +and distracting queue.EMPTY traceback context is no longer added +to tk event exception tracebacks. The traceback is now the same +as when event handling is driven by user code. Patch based on +a suggestion by Serhiy Storchaka. + bpo-32164: Delete unused file idlelib/tabbedpages.py. Use of TabbedPageSet in configdialog was replaced by ttk.Notebook. From webhook-mailer at python.org Tue Dec 5 15:52:22 2017 From: webhook-mailer at python.org (Eric V. Smith) Date: Tue, 05 Dec 2017 20:52:22 -0000 Subject: [Python-checkins] Add dataclasses to CODEOWNERS. (GH-4730) Message-ID: https://github.com/python/cpython/commit/2582f6f24e895d60c35857095706b2a1942c1bed commit: 2582f6f24e895d60c35857095706b2a1942c1bed branch: master author: Eric V. Smith committer: GitHub date: 2017-12-05T15:52:19-05:00 summary: Add dataclasses to CODEOWNERS. (GH-4730) files: M .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8e0647fdc1f..5506ca78101 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -50,4 +50,6 @@ Python/bootstrap_hash.c @python/crypto-team **/*functools* @ncoghlan @rhettinger **/*decimal* @rhettinger @skrah +**/*dataclasses* @ericvsmith + **/*idlelib* @terryjreedy From webhook-mailer at python.org Tue Dec 5 16:56:44 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 05 Dec 2017 21:56:44 -0000 Subject: [Python-checkins] Add Guido and Ivan as owners for typing.py (#4729) Message-ID: https://github.com/python/cpython/commit/5e8cbcc4f25dcdc02651414f792dc4a546ba199b commit: 5e8cbcc4f25dcdc02651414f792dc4a546ba199b branch: master author: Guido van Rossum committer: Ned Deily date: 2017-12-05T16:56:39-05:00 summary: Add Guido and Ivan as owners for typing.py (#4729) files: M .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5506ca78101..3511dcf94a1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -53,3 +53,5 @@ Python/bootstrap_hash.c @python/crypto-team **/*dataclasses* @ericvsmith **/*idlelib* @terryjreedy + +**/*typing* @gvanrossum @ilevkivskyi From lp_benchmark_robot at intel.com Tue Dec 5 17:58:30 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Tue, 5 Dec 2017 14:58:30 -0800 Subject: [Python-checkins] [1 up, 64 flat] Results for Python (master branch) 2017-12-05 Message-ID: <5b111fbb-f364-4a8d-91d4-1d88fce82ec5@orsmsx108.amr.corp.intel.com> Results for project python/master, build date: 2017-12-05 03:03:04-08:00. - commit: ae342cf - previous commit: e69fbb6 - revision date: 2017-12-04 21:05:33-08:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.710% | -0.048% | +4.937% | +8.429% | +-----+------------------------+--------+------------+------------+------------+ | :-) | call_method| 1.759% | +3.900% | +25.180% | +6.181% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.905% | +2.797% | +25.371% | +6.581% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.947% | +3.273% | +23.568% | +4.467% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.068% | -2.358% | +5.351% | +14.059% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.225% | -0.472% | +9.277% | +12.026% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.983% | +0.365% | +7.530% | +10.397% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.479% | -0.207% | +0.250% | +8.070% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.883% | -1.621% | +6.606% | +20.616% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 5.307% | -0.018% | +12.030% | +13.603% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 0.900% | +0.913% | +4.403% | +7.165% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 1.422% | -1.442% | +3.580% | +7.345% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.166% | -0.028% | +2.786% | +7.293% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.286% | -0.743% | +12.777% | +10.938% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.375% | -1.074% | +7.913% | +11.718% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.883% | +0.677% | +6.120% | +12.070% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 1.132% | +0.269% | +10.841% | +11.987% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.044% | +0.966% | +9.140% | +7.836% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.755% | -0.390% | +2.573% | +10.384% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 3.323% | -3.267% | -2.524% | +14.676% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.698% | -0.867% | +5.694% | +13.249% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 4.325% | -0.799% | +46.725% | +14.476% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.626% | -0.389% | +6.539% | +14.630% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.359% | +0.451% | +17.285% | +13.942% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 3.440% | +1.881% | +8.617% | +9.789% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.271% | -0.222% | +3.301% | +6.506% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.806% | +2.216% | -0.147% | -1.061% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 1.082% | -0.607% | +4.077% | +8.427% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.262% | +1.704% | +7.617% | +7.980% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.534% | -0.965% | +0.711% | +21.355% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.257% | -1.942% | -0.765% | +26.548% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.673% | +0.206% | +3.327% | +21.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.190% | -0.044% | +11.985% | +9.347% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.308% | +0.035% | +0.102% | +10.457% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.151% | +0.432% | +10.968% | +4.886% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.110% | +0.351% | +2.133% | +5.216% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.283% | +1.500% | +10.326% | +14.007% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.792% | +0.154% | +0.506% | +9.712% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.338% | -1.067% | -2.400% | +10.672% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.127% | +3.178% | -2.172% | +1.498% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.665% | -3.443% | +4.247% | +9.144% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.234% | +0.118% | +8.251% | +15.665% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.490% | -0.238% | -2.279% | +4.296% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 2.658% | -1.794% | +26.826% | +10.288% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.213% | +0.705% | +4.849% | +6.604% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.803% | +0.453% | +13.730% | +9.896% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.249% | +1.375% | -1.959% | +1.936% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 1.400% | -1.106% | +2.983% | +5.588% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.243% | +0.070% | +6.397% | +6.864% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.643% | -0.332% | +6.630% | +3.287% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.764% | +2.040% | +18.301% | +7.861% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.778% | +0.255% | +11.107% | +7.772% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.743% | +0.675% | +9.347% | +6.805% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.044% | +0.496% | +10.954% | +8.521% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.210% | +0.920% | +10.859% | +9.610% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 5.197% | -0.143% | +19.917% | +14.279% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.008% | -0.225% | +5.909% | +6.085% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.925% | -0.661% | +2.092% | -0.920% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.633% | +3.992% | +8.131% | +19.517% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.662% | -2.254% | -3.573% | +17.116% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.867% | +0.913% | +7.282% | +8.057% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.199% | +0.358% | +5.744% | +9.590% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.737% | -1.902% | +2.184% | +10.063% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.536% | -1.796% | -8.122% | +13.684% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.747% | +0.275% | +6.802% | +9.998% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-up-64-flat-results-for-python-master-branch-2017-12-05 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Tue Dec 5 20:50:49 2017 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 06 Dec 2017 01:50:49 -0000 Subject: [Python-checkins] Tidy NEWS entry. Message-ID: https://github.com/python/cpython/commit/0da25972fd0dc54d76567ea4e3a0bae2d0895e38 commit: 0da25972fd0dc54d76567ea4e3a0bae2d0895e38 branch: 3.6 author: Ned Deily committer: Ned Deily date: 2017-12-05T02:41:31-05:00 summary: Tidy NEWS entry. files: M Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst diff --git a/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst b/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst index b5b6da76d2a..773fa37f8f4 100644 --- a/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst +++ b/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst @@ -1,15 +1,7 @@ Use non-Latin characters in the IDLE's Font settings sample. - Even if one selects a font that defines a limited subset of the unicode - Basic Multilingual Plane, tcl/tk will use other fonts that define a - -character. The expanded example give users of non-Latin characters - +character. The expanded example give users of non-Latin characters a better idea of what they might see in IDLE's shell and editors. - - - To make room for the expanded sample, frames on the Font tab are - -re-arranged. The Font/Tabs help explains a bit about the additions. +re-arranged. The Font/Tabs help explains a bit about the additions. From webhook-mailer at python.org Tue Dec 5 21:06:45 2017 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 06 Dec 2017 02:06:45 -0000 Subject: [Python-checkins] Tidy NEWS entry. Message-ID: https://github.com/python/cpython/commit/d4d2b563025747c2e73ed970c633126a5438044e commit: d4d2b563025747c2e73ed970c633126a5438044e branch: master author: Ned Deily committer: Ned Deily date: 2017-12-05T02:45:57-05:00 summary: Tidy NEWS entry. files: M Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst diff --git a/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst b/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst index b5b6da76d2a..99d4dfd71b5 100644 --- a/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst +++ b/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst @@ -1,15 +1,8 @@ Use non-Latin characters in the IDLE's Font settings sample. - Even if one selects a font that defines a limited subset of the unicode - Basic Multilingual Plane, tcl/tk will use other fonts that define a - character. The expanded example give users of non-Latin characters - a better idea of what they might see in IDLE's shell and editors. - - To make room for the expanded sample, frames on the Font tab are - re-arranged. The Font/Tabs help explains a bit about the additions. From tjreedy at udel.edu Tue Dec 5 22:38:03 2017 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 5 Dec 2017 22:38:03 -0500 Subject: [Python-checkins] Tidy NEWS entry. In-Reply-To: <3ys26j4nqvzFr5t@mail.python.org> References: <3ys26j4nqvzFr5t@mail.python.org> Message-ID: <9d85317e-05b2-034f-1aa2-75579cd6c95a@udel.edu> On 12/5/2017 9:06 PM, Ned Deily wrote: > https://github.com/python/cpython/commit/d4d2b563025747c2e73ed970c633126a5438044e > commit: d4d2b563025747c2e73ed970c633126a5438044e > branch: master > author: Ned Deily > committer: Ned Deily > date: 2017-12-05T02:45:57-05:00 > summary: > > Tidy NEWS entry. > > files: > M Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst > > diff --git a/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst b/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst > index b5b6da76d2a..99d4dfd71b5 100644 > --- a/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst > +++ b/Misc/NEWS.d/next/IDLE/2017-10-12-00-51-29.bpo-13802.VwjZRD.rst > @@ -1,15 +1,8 @@ > Use non-Latin characters in the IDLE's Font settings sample. > - > Even if one selects a font that defines a limited subset of the unicode > - > Basic Multilingual Plane, tcl/tk will use other fonts that define a > - > character. The expanded example give users of non-Latin characters > - > a better idea of what they might see in IDLE's shell and editors. > > - > - > To make room for the expanded sample, frames on the Font tab are > - > re-arranged. The Font/Tabs help explains a bit about the additions. I wrote the news entry with blurb, which opens Notebook on Windows, and did not add the blank lines myself. Something else added them after I saved the file with Notebook. The is the second file where this happened. I updated blurb a couple of days ago from 1.0 to 1.0.5 in case this would make a difference. I rechecked the other files in the idle new dir and the rest look ok. I will try to check the blurb files more carefully before and after making a PR to see if and when this happens again. Terry From solipsis at pitrou.net Wed Dec 6 04:22:24 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 06 Dec 2017 09:22:24 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=14 Message-ID: <20171206092224.73828.0EA35A571210B863@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [7, -7, 8] memory blocks, sum=8 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-1, 2, -2] memory blocks, sum=-1 test_multiprocessing_spawn leaked [-2, 2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogXqFWsV', '--timeout', '7200'] From webhook-mailer at python.org Wed Dec 6 11:25:58 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 06 Dec 2017 16:25:58 -0000 Subject: [Python-checkins] bpo-32030: pass interp to _PyImport_Init() (#4736) Message-ID: https://github.com/python/cpython/commit/672b6baa71010f236ee8c8ce912e98cb542385c6 commit: 672b6baa71010f236ee8c8ce912e98cb542385c6 branch: master author: Victor Stinner committer: GitHub date: 2017-12-06T17:25:50+01:00 summary: bpo-32030: pass interp to _PyImport_Init() (#4736) Remove also the initstr variable, unused since the commit e69f0df45b709c25ac80617c41bbae16f56870fb pushed in 2012: "bpo-13959: Re-implement imp.find_module() in Lib/imp.py" files: M Include/pylifecycle.h M Python/import.c M Python/pylifecycle.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index fa751692a66..4c87428a23a 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -127,7 +127,7 @@ PyAPI_FUNC(const char *) _Py_gitversion(void); PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void); PyAPI_FUNC(_PyInitError) _PySys_BeginInit(PyObject **sysmod); PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict); -PyAPI_FUNC(_PyInitError) _PyImport_Init(void); +PyAPI_FUNC(_PyInitError) _PyImport_Init(PyInterpreterState *interp); PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod); PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void); PyAPI_FUNC(int) _PyFrame_Init(void); diff --git a/Python/import.c b/Python/import.c index 57521e49207..9a9857385cb 100644 --- a/Python/import.c +++ b/Python/import.c @@ -31,8 +31,6 @@ extern struct _inittab _PyImport_Inittab[]; struct _inittab *PyImport_Inittab = _PyImport_Inittab; -static PyObject *initstr = NULL; - /*[clinic input] module _imp [clinic start generated code]*/ @@ -43,14 +41,8 @@ module _imp /* Initialize things */ _PyInitError -_PyImport_Init(void) +_PyImport_Init(PyInterpreterState *interp) { - PyInterpreterState *interp = PyThreadState_Get()->interp; - initstr = PyUnicode_InternFromString("__init__"); - if (initstr == NULL) { - return _Py_INIT_ERR("Can't initialize import variables"); - } - interp->builtins_copy = PyDict_Copy(interp->builtins); if (interp->builtins_copy == NULL) { return _Py_INIT_ERR("Can't backup builtins dict"); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index b615c799989..504036c3ef8 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -751,7 +751,7 @@ _Py_InitializeCore(const _PyCoreConfig *config) PySys_SetObject("__stderr__", pstderr); Py_DECREF(pstderr); - err = _PyImport_Init(); + err = _PyImport_Init(interp); if (_Py_INIT_FAILED(err)) { return err; } From webhook-mailer at python.org Wed Dec 6 11:26:13 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 06 Dec 2017 16:26:13 -0000 Subject: [Python-checkins] bpo-32030: Add pymain_get_global_config() (#4735) Message-ID: https://github.com/python/cpython/commit/6bf992a1ac6f3f4d0f83ead9c6403a76afdbe6eb commit: 6bf992a1ac6f3f4d0f83ead9c6403a76afdbe6eb branch: master author: Victor Stinner committer: GitHub date: 2017-12-06T17:26:10+01:00 summary: bpo-32030: Add pymain_get_global_config() (#4735) * Py_Main() now starts by reading Py_xxx configuration variables to only work on its own private structure, and then later writes back the configuration into these variables. * Replace Py_GETENV() with pymain_get_env_var() which ignores empty variables. * Add _PyCoreConfig.dump_refs * Add _PyCoreConfig.malloc_stats * _PyObject_DebugMallocStats() is now responsible to check if debug hooks are installed. The function returns 1 if stats were written, or 0 if the hooks are disabled. Mark _PyMem_PymallocEnabled() as static. files: M Include/objimpl.h M Include/pymem.h M Include/pystate.h M Modules/main.c M Objects/obmalloc.c M Python/pylifecycle.c M Python/sysmodule.c diff --git a/Include/objimpl.h b/Include/objimpl.h index 746f9c92134..ed9e7a96806 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -109,7 +109,7 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void); /* Macros */ #ifdef WITH_PYMALLOC #ifndef Py_LIMITED_API -PyAPI_FUNC(void) _PyObject_DebugMallocStats(FILE *out); +PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out); #endif /* #ifndef Py_LIMITED_API */ #endif diff --git a/Include/pymem.h b/Include/pymem.h index 09d15020e0e..8ee0efddca7 100644 --- a/Include/pymem.h +++ b/Include/pymem.h @@ -24,10 +24,6 @@ PyAPI_FUNC(int) _PyMem_SetupAllocators(const char *opt); /* Try to get the allocators name set by _PyMem_SetupAllocators(). */ PyAPI_FUNC(const char*) _PyMem_GetAllocatorsName(void); -#ifdef WITH_PYMALLOC -PyAPI_FUNC(int) _PyMem_PymallocEnabled(void); -#endif - /* Track an allocated memory block in the tracemalloc module. Return 0 on success, return -1 on error (failed to allocate memory to store the trace). diff --git a/Include/pystate.h b/Include/pystate.h index cf45b059977..d149aeb2aff 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -36,6 +36,8 @@ typedef struct { int import_time; /* -X importtime */ int show_ref_count; /* -X showrefcount */ int show_alloc_count; /* -X showalloccount */ + int dump_refs; /* PYTHONDUMPREFS */ + int malloc_stats; /* PYTHONMALLOCSTATS */ } _PyCoreConfig; #define _PyCoreConfig_INIT (_PyCoreConfig){.use_hash_seed = -1} @@ -111,7 +113,7 @@ typedef struct _is { PyObject *after_forkers_child; #endif } PyInterpreterState; -#endif +#endif /* !Py_LIMITED_API */ /* State unique per thread */ @@ -133,7 +135,7 @@ typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *); #define PyTrace_C_EXCEPTION 5 #define PyTrace_C_RETURN 6 #define PyTrace_OPCODE 7 -#endif +#endif /* Py_LIMITED_API */ #ifdef Py_LIMITED_API typedef struct _ts PyThreadState; @@ -238,7 +240,7 @@ typedef struct _ts { /* XXX signal handlers should also be here */ } PyThreadState; -#endif +#endif /* !Py_LIMITED_API */ PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void); @@ -363,7 +365,7 @@ PyAPI_FUNC(int) PyGILState_Check(void); Return NULL before _PyGILState_Init() is called and after _PyGILState_Fini() is called. */ PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void); -#endif +#endif /* !Py_LIMITED_API */ /* The implementation of sys._current_frames() Returns a dict mapping diff --git a/Modules/main.c b/Modules/main.c index e2ca72c7dc1..6d53c56e356 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -162,8 +162,8 @@ pymain_get_env_var(const char *name) static void pymain_run_startup(PyCompilerFlags *cf) { - char *startup = Py_GETENV("PYTHONSTARTUP"); - if (startup == NULL || startup[0] == '\0') { + char *startup = pymain_get_env_var("PYTHONSTARTUP"); + if (startup == NULL) { return; } @@ -377,23 +377,28 @@ typedef struct { wchar_t *command; /* -c argument */ wchar_t *module; /* -m argument */ _Py_OptList warning_options; /* -W options */ - PyObject *extra_options; /* -X options */ int print_help; /* -h, -? options */ int print_version; /* -V option */ - int bytes_warning; /* Py_BytesWarningFlag */ - int debug; /* Py_DebugFlag */ - int inspect; /* Py_InspectFlag */ - int interactive; /* Py_InteractiveFlag */ - int isolated; /* Py_IsolatedFlag */ - int optimization_level; /* Py_OptimizeFlag */ - int dont_write_bytecode; /* Py_DontWriteBytecodeFlag */ - int no_user_site_directory; /* Py_NoUserSiteDirectory */ - int no_site_import; /* Py_NoSiteFlag */ - int use_unbuffered_io; /* Py_UnbufferedStdioFlag */ - int verbosity; /* Py_VerboseFlag */ - int quiet_flag; /* Py_QuietFlag */ + int bytes_warning; /* Py_BytesWarningFlag, -b */ + int debug; /* Py_DebugFlag, -b, PYTHONDEBUG */ + int inspect; /* Py_InspectFlag, -i, PYTHONINSPECT */ + int interactive; /* Py_InteractiveFlag, -i */ + int isolated; /* Py_IsolatedFlag, -I */ + int optimization_level; /* Py_OptimizeFlag, -O, PYTHONOPTIMIZE */ + int dont_write_bytecode; /* Py_DontWriteBytecodeFlag, -B, PYTHONDONTWRITEBYTECODE */ + int no_user_site_directory; /* Py_NoUserSiteDirectory, -I, -s, PYTHONNOUSERSITE */ + int no_site_import; /* Py_NoSiteFlag, -S */ + int use_unbuffered_io; /* Py_UnbufferedStdioFlag, -u, PYTHONUNBUFFERED */ + int verbosity; /* Py_VerboseFlag, -v, PYTHONVERBOSE */ + int quiet_flag; /* Py_QuietFlag, -q */ int skip_first_line; /* -x option */ _Py_OptList xoptions; /* -X options */ +#ifdef MS_WINDOWS + int legacy_windows_fs_encoding; /* Py_LegacyWindowsFSEncodingFlag, + PYTHONLEGACYWINDOWSFSENCODING */ + int legacy_windows_stdio; /* Py_LegacyWindowsStdioFlag, + PYTHONLEGACYWINDOWSSTDIO */ +#endif } _Py_CommandLineDetails; /* Structure used by Py_Main() to pass data to subfunctions */ @@ -695,19 +700,6 @@ pymain_parse_cmdline_impl(_PyMain *pymain) } -static void -maybe_set_flag(int *flag, int value) -{ - /* Helper to set flag variables from command line options - * - uses the higher of the two values if they're both set - * - otherwise leaves the flag unset - */ - if (*flag < value) { - *flag = value; - } -} - - static int pymain_add_xoptions(_PyMain *pymain) { @@ -790,9 +782,8 @@ pymain_warnings_envvar(_PyMain *pymain) PyMem_RawFree(buf); } #else - char *p; - - if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') { + char *p = pymain_get_env_var("PYTHONWARNINGS"); + if (p != NULL) { char *buf, *oldloc; /* settle for strtok here as there's no one standard @@ -885,7 +876,6 @@ config_get_program_name(_PyMainInterpreterConfig *config) } #ifdef __APPLE__ - char *p; /* On MacOS X, when the Python interpreter is embedded in an application bundle, it gets executed by a bootstrapping script that does os.execve() with an argv[0] that's different from the @@ -895,7 +885,8 @@ config_get_program_name(_PyMainInterpreterConfig *config) so the actual executable path is passed in an environment variable. See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ - if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') { + char *p = pymain_get_env_var("PYTHONEXECUTABLE"); + if (p != NULL) { size_t len; wchar_t* program_name = Py_DecodeLocale(p, &len); if (program_name == NULL) { @@ -1015,25 +1006,76 @@ pymain_set_argv(_PyMain *pymain) } +static void +pymain_get_flag(int flag, int *value) +{ + if (flag) { + *value = flag; + } +} + +static void +pymain_set_flag(int *flag, int value) +{ + /* Helper to set flag variables from command line options + * - uses the higher of the two values if they're both set + * - otherwise leaves the flag unset + */ + if (*flag < value) { + *flag = value; + } +} + + +/* Get Py_xxx global configuration variables */ +static void +pymain_get_global_config(_PyMain *pymain) +{ + _Py_CommandLineDetails *cmdline = &pymain->cmdline; + pymain_get_flag(Py_BytesWarningFlag, &cmdline->bytes_warning); + pymain_get_flag(Py_DebugFlag, &cmdline->debug); + pymain_get_flag(Py_InspectFlag, &cmdline->inspect); + pymain_get_flag(Py_InteractiveFlag, &cmdline->interactive); + pymain_get_flag(Py_IsolatedFlag, &cmdline->isolated); + pymain_get_flag(Py_OptimizeFlag, &cmdline->optimization_level); + pymain_get_flag(Py_DontWriteBytecodeFlag, &cmdline->dont_write_bytecode); + pymain_get_flag(Py_NoUserSiteDirectory, &cmdline->no_user_site_directory); + pymain_get_flag(Py_NoSiteFlag, &cmdline->no_site_import); + pymain_get_flag(Py_UnbufferedStdioFlag, &cmdline->use_unbuffered_io); + pymain_get_flag(Py_VerboseFlag, &cmdline->verbosity); + pymain_get_flag(Py_QuietFlag, &cmdline->quiet_flag); +#ifdef MS_WINDOWS + pymain_get_flag(Py_LegacyWindowsFSEncodingFlag, &cmdline->legacy_windows_fs_encoding); + pymain_get_flag(Py_LegacyWindowsStdioFlag, &cmdline->legacy_windows_stdio); +#endif + + pymain_get_flag(Py_IgnoreEnvironmentFlag, &pymain->core_config.ignore_environment); +} + + /* Set Py_XXX global configuration variables */ static void pymain_set_global_config(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; - maybe_set_flag(&Py_BytesWarningFlag, cmdline->bytes_warning); - maybe_set_flag(&Py_DebugFlag, cmdline->debug); - maybe_set_flag(&Py_InspectFlag, cmdline->inspect); - maybe_set_flag(&Py_InteractiveFlag, cmdline->interactive); - maybe_set_flag(&Py_IsolatedFlag, cmdline->isolated); - maybe_set_flag(&Py_OptimizeFlag, cmdline->optimization_level); - maybe_set_flag(&Py_DontWriteBytecodeFlag, cmdline->dont_write_bytecode); - maybe_set_flag(&Py_NoUserSiteDirectory, cmdline->no_user_site_directory); - maybe_set_flag(&Py_NoSiteFlag, cmdline->no_site_import); - maybe_set_flag(&Py_UnbufferedStdioFlag, cmdline->use_unbuffered_io); - maybe_set_flag(&Py_VerboseFlag, cmdline->verbosity); - maybe_set_flag(&Py_QuietFlag, cmdline->quiet_flag); - - maybe_set_flag(&Py_IgnoreEnvironmentFlag, pymain->core_config.ignore_environment); + pymain_set_flag(&Py_BytesWarningFlag, cmdline->bytes_warning); + pymain_set_flag(&Py_DebugFlag, cmdline->debug); + pymain_set_flag(&Py_InspectFlag, cmdline->inspect); + pymain_set_flag(&Py_InteractiveFlag, cmdline->interactive); + pymain_set_flag(&Py_IsolatedFlag, cmdline->isolated); + pymain_set_flag(&Py_OptimizeFlag, cmdline->optimization_level); + pymain_set_flag(&Py_DontWriteBytecodeFlag, cmdline->dont_write_bytecode); + pymain_set_flag(&Py_NoUserSiteDirectory, cmdline->no_user_site_directory); + pymain_set_flag(&Py_NoSiteFlag, cmdline->no_site_import); + pymain_set_flag(&Py_UnbufferedStdioFlag, cmdline->use_unbuffered_io); + pymain_set_flag(&Py_VerboseFlag, cmdline->verbosity); + pymain_set_flag(&Py_QuietFlag, cmdline->quiet_flag); +#ifdef MS_WINDOWS + pymain_set_flag(&Py_LegacyWindowsFSEncodingFlag, cmdline->legacy_windows_fs_encoding); + pymain_set_flag(&Py_LegacyWindowsStdioFlag, cmdline->legacy_windows_stdio); +#endif + + pymain_set_flag(&Py_IgnoreEnvironmentFlag, pymain->core_config.ignore_environment); } @@ -1330,24 +1372,25 @@ pymain_set_flag_from_env(int *flag, const char *name) static void pymain_set_flags_from_env(_PyMain *pymain) { - pymain_set_flag_from_env(&Py_DebugFlag, + _Py_CommandLineDetails *cmdline = &pymain->cmdline; + pymain_set_flag_from_env(&cmdline->debug, "PYTHONDEBUG"); - pymain_set_flag_from_env(&Py_VerboseFlag, + pymain_set_flag_from_env(&cmdline->verbosity, "PYTHONVERBOSE"); - pymain_set_flag_from_env(&Py_OptimizeFlag, + pymain_set_flag_from_env(&cmdline->optimization_level, "PYTHONOPTIMIZE"); - pymain_set_flag_from_env(&Py_InspectFlag, + pymain_set_flag_from_env(&cmdline->inspect, "PYTHONINSPECT"); - pymain_set_flag_from_env(&Py_DontWriteBytecodeFlag, + pymain_set_flag_from_env(&cmdline->dont_write_bytecode, "PYTHONDONTWRITEBYTECODE"); - pymain_set_flag_from_env(&Py_NoUserSiteDirectory, + pymain_set_flag_from_env(&cmdline->no_user_site_directory, "PYTHONNOUSERSITE"); - pymain_set_flag_from_env(&Py_UnbufferedStdioFlag, + pymain_set_flag_from_env(&cmdline->use_unbuffered_io, "PYTHONUNBUFFERED"); #ifdef MS_WINDOWS - pymain_set_flag_from_env(&Py_LegacyWindowsFSEncodingFlag, + pymain_set_flag_from_env(&cmdline->legacy_windows_fs_encoding, "PYTHONLEGACYWINDOWSFSENCODING"); - pymain_set_flag_from_env(&Py_LegacyWindowsStdioFlag, + pymain_set_flag_from_env(&cmdline->legacy_windows_stdio, "PYTHONLEGACYWINDOWSSTDIO"); #endif } @@ -1485,7 +1528,7 @@ pymain_parse_envvars(_PyMain *pymain) return -1; } - core_config->allocator = Py_GETENV("PYTHONMALLOC"); + core_config->allocator = pymain_get_env_var("PYTHONMALLOC"); /* -X options */ if (pymain_get_xoption(pymain, L"showrefcount")) { @@ -1514,6 +1557,14 @@ pymain_parse_envvars(_PyMain *pymain) core_config->faulthandler = 1; core_config->allocator = "debug"; } + if (pymain_get_env_var("PYTHONDUMPREFS")) { + pymain->core_config.dump_refs = 1; + } + if (pymain_get_env_var("PYTHONMALLOCSTATS")) { + pymain->core_config.malloc_stats = 1; + } + + return 0; } @@ -1535,6 +1586,7 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) return 1; } + /* Set Py_IgnoreEnvironmentFlag needed by Py_GETENV() */ pymain_set_global_config(pymain); if (pymain_parse_envvars(pymain) < 0) { @@ -1568,6 +1620,8 @@ pymain_parse_cmdline_envvars(_PyMain *pymain) static int pymain_init_python(_PyMain *pymain) { + pymain_set_global_config(pymain); + pymain_init_stdio(pymain); pymain->err = _Py_InitializeCore(&pymain->core_config); @@ -1641,6 +1695,8 @@ pymain_impl(_PyMain *pymain) return -1; } + pymain_get_global_config(pymain); + res = pymain_parse_cmdline_envvars(pymain); if (res < 0) { return -1; diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 7911028ad83..c065541458b 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -379,7 +379,7 @@ _PyMem_DebugEnabled(void) return (_PyObject.malloc == _PyMem_DebugMalloc); } -int +static int _PyMem_PymallocEnabled(void) { if (_PyMem_DebugEnabled()) { @@ -2467,10 +2467,17 @@ pool_is_in_list(const poolp target, poolp list) /* Print summary info to "out" about the state of pymalloc's structures. * In Py_DEBUG mode, also perform some expensive internal consistency * checks. + * + * Return 0 if the memory debug hooks are not installed or no statistics was + * writen into out, return 1 otherwise. */ -void +int _PyObject_DebugMallocStats(FILE *out) { + if (!_PyMem_PymallocEnabled()) { + return 0; + } + uint i; const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT; /* # of pools, allocated blocks, and free blocks per class index */ @@ -2603,6 +2610,7 @@ _PyObject_DebugMallocStats(FILE *out) total += printone(out, "# bytes lost to quantization", quantization); total += printone(out, "# bytes lost to arena alignment", arena_alignment); (void)printone(out, "Total", total); + return 1; } #endif /* #ifdef WITH_PYMALLOC */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 504036c3ef8..0b3aa98ba2e 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1103,6 +1103,10 @@ Py_FinalizeEx(void) tstate = PyThreadState_GET(); interp = tstate->interp; + /* Copy the core config to be able to use it even + after PyInterpreterState_Delete() */ + _PyCoreConfig core_config = interp->core_config; + /* Remaining threads (e.g. daemon threads) will automatically exit after taking the GIL (in PyEval_RestoreThread()). */ _PyRuntime.finalizing = tstate; @@ -1186,7 +1190,7 @@ Py_FinalizeEx(void) _PyHash_Fini(); #ifdef Py_REF_DEBUG - if (interp->core_config.show_ref_count) { + if (core_config.show_ref_count) { _PyDebug_PrintTotalRefs(); } #endif @@ -1197,8 +1201,9 @@ Py_FinalizeEx(void) * Alas, a lot of stuff may still be alive now that will be cleaned * up later. */ - if (Py_GETENV("PYTHONDUMPREFS")) + if (core_config.dump_refs) { _Py_PrintReferences(stderr); + } #endif /* Py_TRACE_REFS */ /* Clear interpreter state and all thread states. */ @@ -1260,14 +1265,13 @@ Py_FinalizeEx(void) * An address can be used to find the repr of the object, printed * above by _Py_PrintReferences. */ - if (Py_GETENV("PYTHONDUMPREFS")) + if (core_config.dump_refs) { _Py_PrintReferenceAddresses(stderr); + } #endif /* Py_TRACE_REFS */ #ifdef WITH_PYMALLOC - if (_PyMem_PymallocEnabled()) { - char *opt = Py_GETENV("PYTHONMALLOCSTATS"); - if (opt != NULL && *opt != '\0') - _PyObject_DebugMallocStats(stderr); + if (core_config.malloc_stats) { + _PyObject_DebugMallocStats(stderr); } #endif diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 64bc14e9c3d..eeeaa7240e7 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1368,8 +1368,7 @@ static PyObject * sys_debugmallocstats(PyObject *self, PyObject *args) { #ifdef WITH_PYMALLOC - if (_PyMem_PymallocEnabled()) { - _PyObject_DebugMallocStats(stderr); + if (_PyObject_DebugMallocStats(stderr)) { fputc('\n', stderr); } #endif From webhook-mailer at python.org Wed Dec 6 11:39:37 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 06 Dec 2017 16:39:37 -0000 Subject: [Python-checkins] bpo-25910: Fixes redirection from http to https (#4674) Message-ID: https://github.com/python/cpython/commit/1b4587a2462fc05a14be87123083322103a1f55b commit: 1b4587a2462fc05a14be87123083322103a1f55b branch: master author: Sanyam Khurana <8039608+CuriousLearner at users.noreply.github.com> committer: Victor Stinner date: 2017-12-06T17:39:33+01:00 summary: bpo-25910: Fixes redirection from http to https (#4674) files: M Doc/bugs.rst M Doc/faq/design.rst M Doc/faq/gui.rst M Doc/faq/library.rst M Doc/faq/programming.rst M Doc/faq/windows.rst M Doc/glossary.rst M Doc/howto/curses.rst M Doc/howto/pyporting.rst M Doc/howto/unicode.rst M Doc/library/email.generator.rst M Doc/library/hashlib.rst M Doc/library/othergui.rst M Doc/library/secrets.rst M Doc/library/select.rst M Doc/library/sqlite3.rst M Doc/library/ssl.rst M Doc/library/tkinter.rst M Doc/library/unittest.rst M Doc/tutorial/interactive.rst M Doc/using/mac.rst M Doc/using/windows.rst M Doc/whatsnew/2.7.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/bugs.rst b/Doc/bugs.rst index bc1d10f379c..109e9eb202d 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -68,7 +68,7 @@ taken on the bug. .. seealso:: - `How to Report Bugs Effectively `_ + `How to Report Bugs Effectively `_ Article which goes into some detail about how to create a useful bug report. This describes what kind of information is useful and why it is useful. diff --git a/Doc/faq/design.rst b/Doc/faq/design.rst index 1bd800b1a81..2e56fbc2f42 100644 --- a/Doc/faq/design.rst +++ b/Doc/faq/design.rst @@ -343,7 +343,7 @@ each Python stack frame. Also, extensions can call back into Python at almost random moments. Therefore, a complete threads implementation requires thread support for C. -Answer 2: Fortunately, there is `Stackless Python `_, +Answer 2: Fortunately, there is `Stackless Python `_, which has a completely redesigned interpreter loop that avoids the C stack. diff --git a/Doc/faq/gui.rst b/Doc/faq/gui.rst index 38e1796267f..4f9979bf55e 100644 --- a/Doc/faq/gui.rst +++ b/Doc/faq/gui.rst @@ -43,7 +43,7 @@ number of platforms, with Windows, Mac OS X, GTK, X11, all listed as current stable targets. Language bindings are available for a number of languages including Python, Perl, Ruby, etc. -wxPython (http://www.wxpython.org) is the Python binding for +`wxPython `_ is the Python binding for wxwidgets. While it often lags slightly behind the official wxWidgets releases, it also offers a number of features via pure Python extensions that are not available in other language bindings. There @@ -72,9 +72,9 @@ Gtk+ The `GObject introspection bindings `_ for Python allow you to write GTK+ 3 applications. There is also a -`Python GTK+ 3 Tutorial `_. +`Python GTK+ 3 Tutorial `_. -The older PyGtk bindings for the `Gtk+ 2 toolkit `_ have +The older PyGtk bindings for the `Gtk+ 2 toolkit `_ have been implemented by James Henstridge; see . Kivy diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index b5fdfa42cdb..f84feadd780 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -419,7 +419,7 @@ Python program effectively only uses one CPU, due to the insistence that Back in the days of Python 1.5, Greg Stein actually implemented a comprehensive patch set (the "free threading" patches) that removed the GIL and replaced it with fine-grained locking. Adam Olsen recently did a similar experiment -in his `python-safethread `_ +in his `python-safethread `_ project. Unfortunately, both experiments exhibited a sharp drop in single-thread performance (at least 30% slower), due to the amount of fine-grained locking necessary to compensate for the removal of the GIL. diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 1022373d387..1a2f582a31a 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -100,7 +100,7 @@ which don't. One is Thomas Heller's py2exe (Windows only) at http://www.py2exe.org/ -Another tool is Anthony Tuininga's `cx_Freeze `_. +Another tool is Anthony Tuininga's `cx_Freeze `_. Are there coding standards or a style guide for Python programs? diff --git a/Doc/faq/windows.rst b/Doc/faq/windows.rst index 6ac83e45d2e..d703f286222 100644 --- a/Doc/faq/windows.rst +++ b/Doc/faq/windows.rst @@ -170,8 +170,8 @@ offender. How do I make an executable from a Python script? ------------------------------------------------- -See http://cx-freeze.sourceforge.net/ for a distutils extension that allows you -to create console and GUI executables from Python code. +See `cx_Freeze `_ for a distutils extension +that allows you to create console and GUI executables from Python code. `py2exe `_, the most popular extension for building Python 2.x-based executables, does not yet support Python 3 but a version that does is in development. diff --git a/Doc/glossary.rst b/Doc/glossary.rst index b947520b96b..ba4d300c0e9 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -126,7 +126,7 @@ Glossary BDFL Benevolent Dictator For Life, a.k.a. `Guido van Rossum - `_, Python's creator. + `_, Python's creator. binary file A :term:`file object` able to read and write diff --git a/Doc/howto/curses.rst b/Doc/howto/curses.rst index 1d3bfb87dc0..19d65d6996b 100644 --- a/Doc/howto/curses.rst +++ b/Doc/howto/curses.rst @@ -543,7 +543,7 @@ learn more about submitting patches to Python. * `Writing Programs with NCURSES `_: a lengthy tutorial for C programmers. -* `The ncurses man page `_ +* `The ncurses man page `_ * `The ncurses FAQ `_ * `"Use curses... don't swear" `_: video of a PyCon 2013 talk on controlling terminals using curses or Urwid. diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 8562d237374..bec6a3d72ce 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -449,4 +449,4 @@ to make sure everything functions as expected in both versions of Python. .. _"What's New": https://docs.python.org/3/whatsnew/index.html -.. _Why Python 3 exists: http://www.snarky.ca/why-python-3-exists +.. _Why Python 3 exists: https://snarky.ca/why-python-3-exists diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst index 9649b9c609c..a83e5a21895 100644 --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -217,7 +217,7 @@ To help understand the standard, Jukka Korpela has written `an introductory guide `_ to reading the Unicode character tables. -Another `good introductory article `_ +Another `good introductory article `_ was written by Joel Spolsky. If this introduction didn't make things clear to you, you should try reading this alternate article before continuing. @@ -487,7 +487,7 @@ References Some good alternative discussions of Python's Unicode support are: * `Processing Text Files in Python 3 `_, by Nick Coghlan. -* `Pragmatic Unicode `_, a PyCon 2012 presentation by Ned Batchelder. +* `Pragmatic Unicode `_, a PyCon 2012 presentation by Ned Batchelder. The :class:`str` type is described in the Python library reference at :ref:`textseq`. diff --git a/Doc/library/email.generator.rst b/Doc/library/email.generator.rst index 1e64e1066c7..cc8e8225a20 100644 --- a/Doc/library/email.generator.rst +++ b/Doc/library/email.generator.rst @@ -53,7 +53,7 @@ over channels that are not "8 bit clean". :data:`~email.policy.compat32` policy and ``False`` for all others). *mangle_from_* is intended for use when messages are stored in unix mbox format (see :mod:`mailbox` and `WHY THE CONTENT-LENGTH FORMAT IS BAD - `_). + `_). If *maxheaderlen* is not ``None``, refold any header lines that are longer than *maxheaderlen*, or if ``0``, do not rewrap any headers. If @@ -154,7 +154,7 @@ to be using :class:`BytesGenerator`, and not :class:`Generator`. :data:`~email.policy.compat32` policy and ``False`` for all others). *mangle_from_* is intended for use when messages are stored in unix mbox format (see :mod:`mailbox` and `WHY THE CONTENT-LENGTH FORMAT IS BAD - `_). + `_). If *maxheaderlen* is not ``None``, refold any header lines that are longer than *maxheaderlen*, or if ``0``, do not rewrap any headers. If diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index 452705f4d2a..d4916914f79 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -482,7 +482,7 @@ Keyed hashing Keyed hashing can be used for authentication as a faster and simpler replacement for `Hash-based message authentication code -`_ (HMAC). +`_ (HMAC). BLAKE2 can be securely used in prefix-MAC mode thanks to the indifferentiability property inherited from BLAKE. @@ -699,7 +699,7 @@ implementation, extension code, and this documentation: You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see - http://creativecommons.org/publicdomain/zero/1.0/. + https://creativecommons.org/publicdomain/zero/1.0/. The following people have helped with development or contributed their changes to the project and the public domain according to the Creative Commons Public diff --git a/Doc/library/othergui.rst b/Doc/library/othergui.rst index d40abe16765..4548459f8e2 100644 --- a/Doc/library/othergui.rst +++ b/Doc/library/othergui.rst @@ -11,9 +11,9 @@ available for Python: `PyGObject `_ PyGObject provides introspection bindings for C libraries using `GObject `_. One of - these libraries is the `GTK+ 3 `_ widget set. + these libraries is the `GTK+ 3 `_ widget set. GTK+ comes with many more widgets than Tkinter provides. An online - `Python GTK+ 3 Tutorial `_ + `Python GTK+ 3 Tutorial `_ is available. `PyGTK `_ @@ -35,7 +35,7 @@ available for Python: Compared to PyQt, its licensing scheme is friendlier to non-open source applications. - `wxPython `_ + `wxPython `_ wxPython is a cross-platform GUI toolkit for Python that is built around the popular `wxWidgets `_ (formerly wxWindows) C++ toolkit. It provides a native look and feel for applications on diff --git a/Doc/library/secrets.rst b/Doc/library/secrets.rst index 9bf848f9114..28ce472c7e7 100644 --- a/Doc/library/secrets.rst +++ b/Doc/library/secrets.rst @@ -130,7 +130,7 @@ Other functions Return ``True`` if strings *a* and *b* are equal, otherwise ``False``, in such a way as to reduce the risk of - `timing attacks `_. + `timing attacks `_. See :func:`hmac.compare_digest` for additional details. @@ -173,7 +173,7 @@ three digits: break -Generate an `XKCD-style passphrase `_: +Generate an `XKCD-style passphrase `_: .. testcode:: diff --git a/Doc/library/select.rst b/Doc/library/select.rst index bd5442c6a27..e252e7adb92 100644 --- a/Doc/library/select.rst +++ b/Doc/library/select.rst @@ -264,7 +264,7 @@ object. Edge and Level Trigger Polling (epoll) Objects ---------------------------------------------- - http://linux.die.net/man/4/epoll + https://linux.die.net/man/4/epoll *eventmask* diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index c7b9af4037f..e7676a9f3a5 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -107,7 +107,7 @@ This example uses the iterator form:: The SQLite web page; the documentation describes the syntax and the available data types for the supported SQL dialect. - http://www.w3schools.com/sql/ + https://www.w3schools.com/sql/ Tutorial, reference and examples for learning SQL syntax. :pep:`249` - Database API Specification 2.0 diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 45bb65ff071..6122af18ede 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1590,7 +1590,7 @@ to speed up repeated connections from the same clients. .. versionadded:: 3.3 .. seealso:: - `SSL/TLS & Perfect Forward Secrecy `_ + `SSL/TLS & Perfect Forward Secrecy `_ Vincent Bernat. .. method:: SSLContext.wrap_socket(sock, server_side=False, \ diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index f51add2b41f..f222fe6f8b2 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -38,7 +38,7 @@ this should open a window demonstrating a simple Tk interface. `Programming Python `_ Book by Mark Lutz, has excellent coverage of Tkinter. - `Modern Tkinter for Busy Python Developers `_ + `Modern Tkinter for Busy Python Developers `_ Book by Mark Rozerman about building attractive and modern graphical user interfaces with Python and Tkinter. `Python and Tkinter Programming `_ @@ -183,7 +183,7 @@ documentation that exists. Here are some hints: `ActiveState Tcl Home Page `_ The Tk/Tcl development is largely taking place at ActiveState. - `Tcl and the Tk Toolkit `_ + `Tcl and the Tk Toolkit `_ The book by John Ousterhout, the inventor of Tcl. `Practical Programming in Tcl and Tk `_ diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 4755488d91d..93ccd0fd611 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -56,7 +56,7 @@ test runner Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. - `Nose `_ and `py.test `_ + `Nose `_ and `py.test `_ Third-party unittest frameworks with a lighter-weight syntax for writing tests. For example, ``assert func(10) == 42``. diff --git a/Doc/tutorial/interactive.rst b/Doc/tutorial/interactive.rst index d73cfeb34f1..c0eb1feec4e 100644 --- a/Doc/tutorial/interactive.rst +++ b/Doc/tutorial/interactive.rst @@ -51,4 +51,4 @@ bpython_. .. _GNU Readline: https://tiswww.case.edu/php/chet/readline/rltop.html .. _IPython: https://ipython.org/ -.. _bpython: http://www.bpython-interpreter.org/ +.. _bpython: https://www.bpython-interpreter.org/ diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 8f1ac3f3fd3..b89c98709ea 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -149,7 +149,7 @@ X by Apple, and the latest version can be downloaded and installed from https://www.activestate.com; it can also be built from source. *wxPython* is another popular cross-platform GUI toolkit that runs natively on -Mac OS X. Packages and documentation are available from http://www.wxpython.org. +Mac OS X. Packages and documentation are available from https://www.wxpython.org. *PyQt* is another popular cross-platform GUI toolkit that runs natively on Mac OS X. More information can be found at diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 3d47d7c5154..cc560d968a1 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -291,9 +291,9 @@ for detailed information about platforms with pre-compiled installers. by Mark Pilgrim, 2004, ISBN 1-59059-356-1 - `For Windows users `_ + `For Windows users `_ in "Installing Python" - in "`A Byte of Python `_" + in "`A Byte of Python `_" by Swaroop C H, 2003 @@ -871,7 +871,7 @@ shipped with PyWin32. It is an embeddable IDE with a built-in debugger. cx_Freeze --------- -`cx_Freeze `_ is a :mod:`distutils` +`cx_Freeze `_ is a :mod:`distutils` extension (see :ref:`extending-distutils`) which wraps Python scripts into executable Windows programs (:file:`{*}.exe` files). When you have done this, you can distribute your application without requiring your users to install diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 55392fc2be0..eec89845395 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -1809,7 +1809,7 @@ wish to read the Tcl/Tk manual page describing the Ttk theme engine, available at https://www.tcl.tk/man/tcl8.5/TkCmd/ttk_intro.htm. Some screenshots of the Python/Ttk code in use are at -http://code.google.com/p/python-ttk/wiki/Screenshots. +https://code.google.com/archive/p/python-ttk/wikis/Screenshots.wiki. The :mod:`ttk` module was written by Guilherme Polo and added in :issue:`2983`. An alternate version called ``Tile.py``, written by @@ -1832,8 +1832,8 @@ https://pypi.python.org/pypi/unittest2. When used from the command line, the module can automatically discover tests. It's not as fancy as `py.test `__ or -`nose `__, but provides a simple way -to run tests kept within a set of package directories. For example, +`nose `__, but provides a +simple way to run tests kept within a set of package directories. For example, the following command will search the :file:`test/` subdirectory for any importable test files named ``test*.py``:: diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 60469cd1d36..67c86df0207 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -238,8 +238,8 @@ and the ``__annotations__`` attribute. and Guido van Rossum. Implemented by Ivan Levkivskyi. Tools that use or will use the new syntax: - `mypy `_, - `pytype `_, PyCharm, etc. + `mypy `_, + `pytype `_, PyCharm, etc. .. _whatsnew36-pep515: From webhook-mailer at python.org Wed Dec 6 12:13:02 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 06 Dec 2017 17:13:02 -0000 Subject: [Python-checkins] bpo-32030: Add _PyImport_Fini2() (#4737) Message-ID: https://github.com/python/cpython/commit/92a3c6f493ad411e4cf0acdf305ef4876aa90669 commit: 92a3c6f493ad411e4cf0acdf305ef4876aa90669 branch: master author: Victor Stinner committer: GitHub date: 2017-12-06T18:12:59+01:00 summary: bpo-32030: Add _PyImport_Fini2() (#4737) PyImport_ExtendInittab() now uses PyMem_RawRealloc() rather than PyMem_Realloc(). PyImport_ExtendInittab() can be called before Py_Initialize() whereas only the PyMem_Raw allocator is supposed to be used before Py_Initialize(). Add _PyImport_Fini2() to release the memory allocated by PyImport_ExtendInittab() at exit. PyImport_ExtendInittab() now forces the usage of the default raw allocator, to be able to release memory in _PyImport_Fini2(). Don't export these functions anymore to be C API, only to Py_BUILD_CORE: * _PyExc_Fini() * _PyImport_Fini() * _PyGC_DumpShutdownStats() * _PyGC_Fini() * _PyType_Fini() * _Py_HashRandomization_Fini() files: M Include/pylifecycle.h M Modules/main.c M Python/import.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 4c87428a23a..bda51f84c3c 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -137,9 +137,18 @@ PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(_PyCoreConfig *core_config); #endif /* Various internal finalizers */ -#ifndef Py_LIMITED_API + +#ifdef Py_BUILD_CORE PyAPI_FUNC(void) _PyExc_Fini(void); PyAPI_FUNC(void) _PyImport_Fini(void); +PyAPI_FUNC(void) _PyImport_Fini2(void); +PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); +PyAPI_FUNC(void) _PyGC_Fini(void); +PyAPI_FUNC(void) _PyType_Fini(void); +PyAPI_FUNC(void) _Py_HashRandomization_Fini(void); +#endif /* Py_BUILD_CORE */ + +#ifndef Py_LIMITED_API PyAPI_FUNC(void) PyMethod_Fini(void); PyAPI_FUNC(void) PyFrame_Fini(void); PyAPI_FUNC(void) PyCFunction_Fini(void); @@ -151,15 +160,11 @@ PyAPI_FUNC(void) PyBytes_Fini(void); PyAPI_FUNC(void) PyByteArray_Fini(void); PyAPI_FUNC(void) PyFloat_Fini(void); PyAPI_FUNC(void) PyOS_FiniInterrupts(void); -PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); -PyAPI_FUNC(void) _PyGC_Fini(void); PyAPI_FUNC(void) PySlice_Fini(void); -PyAPI_FUNC(void) _PyType_Fini(void); -PyAPI_FUNC(void) _Py_HashRandomization_Fini(void); PyAPI_FUNC(void) PyAsyncGen_Fini(void); PyAPI_FUNC(int) _Py_IsFinalizing(void); -#endif +#endif /* !Py_LIMITED_API */ /* Signals */ typedef void (*PyOS_sighandler_t)(int); diff --git a/Modules/main.c b/Modules/main.c index 6d53c56e356..4ab1ff29fac 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -446,17 +446,18 @@ pymain_optlist_clear(_Py_OptList *list) list->options = NULL; } -static void -pymain_free_impl(_PyMain *pymain) -{ - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - pymain_optlist_clear(&cmdline->warning_options); - pymain_optlist_clear(&cmdline->xoptions); - PyMem_RawFree(cmdline->command); - pymain_optlist_clear(&pymain->env_warning_options); - Py_CLEAR(pymain->main_importer_path); +/* Free global variables which cannot be freed in Py_Finalize(): + configuration options set before Py_Initialize() which should + remain valid after Py_Finalize(), since Py_Initialize()/Py_Finalize() can + be called multiple times. + Called with the current memory allocators. */ +static void +pymain_free_globals(_PyMain *pymain) +{ + _PyPathConfig_Clear(&_Py_path_config); + _PyImport_Fini2(); _PyMainInterpreterConfig_Clear(&pymain->config); #ifdef __INSURE__ @@ -473,6 +474,20 @@ pymain_free_impl(_PyMain *pymain) #endif /* __INSURE__ */ } + +static void +pymain_free_pymain(_PyMain *pymain) +{ + _Py_CommandLineDetails *cmdline = &pymain->cmdline; + pymain_optlist_clear(&cmdline->warning_options); + pymain_optlist_clear(&cmdline->xoptions); + PyMem_RawFree(cmdline->command); + + pymain_optlist_clear(&pymain->env_warning_options); + Py_CLEAR(pymain->main_importer_path); + +} + static void pymain_free(_PyMain *pymain) { @@ -480,12 +495,12 @@ pymain_free(_PyMain *pymain) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - pymain_free_impl(pymain); + pymain_free_pymain(pymain); + pymain_free_globals(pymain); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } - static int pymain_run_main_from_importer(_PyMain *pymain) { @@ -1719,13 +1734,6 @@ pymain_impl(_PyMain *pymain) pymain->status = 120; } - /* _PyPathConfig_Clear() cannot be called in Py_FinalizeEx(). - Py_Initialize() and Py_Finalize() can be called multiple times, but it - must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or - Py_SetPythonHome(), whereas _PyPathConfig_Clear() clear all these - parameters. */ - _PyPathConfig_Clear(&_Py_path_config); - return 0; } diff --git a/Python/import.c b/Python/import.c index 9a9857385cb..cc7417ba84e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -30,6 +30,7 @@ static PyObject *extensions = NULL; extern struct _inittab _PyImport_Inittab[]; struct _inittab *PyImport_Inittab = _PyImport_Inittab; +static struct _inittab *inittab_copy = NULL; /*[clinic input] module _imp @@ -285,6 +286,19 @@ _PyImport_Fini(void) } } +void +_PyImport_Fini2(void) +{ + /* Use the same memory allocator than PyImport_ExtendInittab(). */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + /* Free memory allocated by PyImport_ExtendInittab() */ + PyMem_RawFree(inittab_copy); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + /* Helper for sys */ PyObject * @@ -2233,9 +2247,9 @@ PyInit_imp(void) int PyImport_ExtendInittab(struct _inittab *newtab) { - static struct _inittab *our_copy = NULL; struct _inittab *p; - int i, n; + Py_ssize_t i, n; + int res = 0; /* Count the number of entries in both tables */ for (n = 0; newtab[n].name != NULL; n++) @@ -2245,19 +2259,35 @@ PyImport_ExtendInittab(struct _inittab *newtab) for (i = 0; PyImport_Inittab[i].name != NULL; i++) ; + /* Force default raw memory allocator to get a known allocator to be able + to release the memory in _PyImport_Fini2() */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* Allocate new memory for the combined table */ - p = our_copy; - PyMem_RESIZE(p, struct _inittab, i+n+1); - if (p == NULL) - return -1; + if ((i + n + 1) <= PY_SSIZE_T_MAX / sizeof(struct _inittab)) { + size_t size = sizeof(struct _inittab) * (i + n + 1); + p = PyMem_RawRealloc(inittab_copy, size); + } + else { + p = NULL; + } + if (p == NULL) { + res = -1; + goto done; + } - /* Copy the tables into the new memory */ - if (our_copy != PyImport_Inittab) + /* Copy the tables into the new memory at the first call + to PyImport_ExtendInittab(). */ + if (inittab_copy != PyImport_Inittab) { memcpy(p, PyImport_Inittab, (i+1) * sizeof(struct _inittab)); - PyImport_Inittab = our_copy = p; - memcpy(p+i, newtab, (n+1) * sizeof(struct _inittab)); + } + memcpy(p + i, newtab, (n + 1) * sizeof(struct _inittab)); + PyImport_Inittab = inittab_copy = p; - return 0; +done: + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + return res; } /* Shorthand to add a single entry given a name and a function */ From webhook-mailer at python.org Wed Dec 6 12:24:23 2017 From: webhook-mailer at python.org (Stefan Krah) Date: Wed, 06 Dec 2017 17:24:23 -0000 Subject: [Python-checkins] bpo-32233: Fix build with --with-system-libmpdec. (#4739) Message-ID: https://github.com/python/cpython/commit/bd4ed77f73d37df325fc8f1e193b3ce6bc08094d commit: bd4ed77f73d37df325fc8f1e193b3ce6bc08094d branch: master author: Stefan Krah committer: GitHub date: 2017-12-06T18:24:17+01:00 summary: bpo-32233: Fix build with --with-system-libmpdec. (#4739) files: M setup.py diff --git a/setup.py b/setup.py index c22de17f953..09e35e50609 100644 --- a/setup.py +++ b/setup.py @@ -2069,6 +2069,7 @@ def _decimal_ext(self): 'Modules', '_decimal', 'libmpdec'))] + libraries = ['m'] sources = [ '_decimal/_decimal.c', '_decimal/libmpdec/basearith.c', @@ -2164,7 +2165,7 @@ def _decimal_ext(self): ext = Extension ( '_decimal', include_dirs=include_dirs, - libraries=['m'], + libraries=libraries, define_macros=define_macros, undef_macros=undef_macros, extra_compile_args=extra_compile_args, From webhook-mailer at python.org Wed Dec 6 12:58:21 2017 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Wed, 06 Dec 2017 17:58:21 -0000 Subject: [Python-checkins] Modify configure to link with the compiler driver under HP-UX when not using gcc. (#2519) Message-ID: https://github.com/python/cpython/commit/9d25bd11ca121cfc76e5bf31c265e72956208598 commit: 9d25bd11ca121cfc76e5bf31c265e72956208598 branch: master author: Rob Boehne committer: ?ukasz Langa date: 2017-12-06T09:58:17-08:00 summary: Modify configure to link with the compiler driver under HP-UX when not using gcc. (#2519) files: M configure M configure.ac diff --git a/configure b/configure index d02675742d2..20d8095c252 100755 --- a/configure +++ b/configure @@ -9124,7 +9124,8 @@ then LDSHARED='$(CC) -shared' LDCXXSHARED='$(CXX) -shared' else - LDSHARED='ld -b' + LDSHARED='$(CC) -b' + LDCXXSHARED='$(CXX) -shared' fi ;; Darwin/1.3*) LDSHARED='$(CC) -bundle' diff --git a/configure.ac b/configure.ac index 68a95c3be6a..828dadb56c4 100644 --- a/configure.ac +++ b/configure.ac @@ -2442,7 +2442,8 @@ then LDSHARED='$(CC) -shared' LDCXXSHARED='$(CXX) -shared' else - LDSHARED='ld -b' + LDSHARED='$(CC) -b' + LDCXXSHARED='$(CXX) -b' fi ;; Darwin/1.3*) LDSHARED='$(CC) -bundle' From webhook-mailer at python.org Wed Dec 6 14:00:37 2017 From: webhook-mailer at python.org (Eric V. Smith) Date: Wed, 06 Dec 2017 19:00:37 -0000 Subject: [Python-checkins] Use raw strings for regex to avoid invalid escape sequences. (GH-4741) Message-ID: https://github.com/python/cpython/commit/24e77f92658c7d258e2a3cf9868f3f4658932b40 commit: 24e77f92658c7d258e2a3cf9868f3f4658932b40 branch: master author: Eric V. Smith committer: GitHub date: 2017-12-06T14:00:34-05:00 summary: Use raw strings for regex to avoid invalid escape sequences. (GH-4741) files: M Lib/test/test_dataclasses.py diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index caea98a13b0..9d08a2d4c91 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1831,7 +1831,7 @@ class C: # if we're also replacing one that does exist. Test this # here, because setting attributes on frozen instances is # handled slightly differently from non-frozen ones. - with self.assertRaisesRegex(TypeError, "__init__\(\) got an unexpected " + with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " "keyword argument 'a'"): c1 = replace(c, x=20, a=5) @@ -1842,7 +1842,7 @@ class C: y: int c = C(1, 2) - with self.assertRaisesRegex(TypeError, "__init__\(\) got an unexpected " + with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " "keyword argument 'z'"): c1 = replace(c, z=3) From webhook-mailer at python.org Wed Dec 6 14:33:18 2017 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 06 Dec 2017 19:33:18 -0000 Subject: [Python-checkins] Allows non-critical upload steps to fail (#4742) Message-ID: https://github.com/python/cpython/commit/9ab11b3a029fba36c1a7e869be87fb4f31ebcf24 commit: 9ab11b3a029fba36c1a7e869be87fb4f31ebcf24 branch: master author: Steve Dower committer: GitHub date: 2017-12-06T11:33:15-08:00 summary: Allows non-critical upload steps to fail (#4742) files: M Tools/msi/uploadrelease.proj diff --git a/Tools/msi/uploadrelease.proj b/Tools/msi/uploadrelease.proj index 881b825e107..96b99a4ff63 100644 --- a/Tools/msi/uploadrelease.proj +++ b/Tools/msi/uploadrelease.proj @@ -52,11 +52,11 @@ - + - + - + From webhook-mailer at python.org Wed Dec 6 15:12:47 2017 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 06 Dec 2017 20:12:47 -0000 Subject: [Python-checkins] Allows non-critical upload steps to fail (GH-4742) (#4743) Message-ID: https://github.com/python/cpython/commit/8676ac5419b9518d18c57ed32ea4796b218135f4 commit: 8676ac5419b9518d18c57ed32ea4796b218135f4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower date: 2017-12-06T12:12:44-08:00 summary: Allows non-critical upload steps to fail (GH-4742) (#4743) (cherry picked from commit 9ab11b3a029fba36c1a7e869be87fb4f31ebcf24) files: M Tools/msi/uploadrelease.proj diff --git a/Tools/msi/uploadrelease.proj b/Tools/msi/uploadrelease.proj index 881b825e107..96b99a4ff63 100644 --- a/Tools/msi/uploadrelease.proj +++ b/Tools/msi/uploadrelease.proj @@ -52,11 +52,11 @@ - + - + - + From lp_benchmark_robot at intel.com Wed Dec 6 17:30:17 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 6 Dec 2017 14:30:17 -0800 Subject: [Python-checkins] [1 down, 1 up, 63 flat] Results for Python (master branch) 2017-12-06 Message-ID: Results for project python/master, build date: 2017-12-06 03:03:17-08:00. - commit: a2a25eb - previous commit: ae342cf - revision date: 2017-12-05 21:06:12-05:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.841% | +0.377% | +5.295% | +8.075% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.467% | -2.014% | +23.673% | +11.514% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 4.235% | -1.088% | +24.559% | +10.303% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.924% | -0.744% | +22.999% | +11.316% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.575% | +0.656% | +5.972% | +12.339% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.003% | +0.297% | +9.547% | +13.929% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.596% | -1.258% | +6.367% | +12.122% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.441% | -0.522% | -0.270% | +8.739% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.173% | +3.086% | +9.488% | +19.478% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 7.384% | -3.295% | +9.131% | +18.716% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.494% | +0.184% | +4.579% | +6.880% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 1.347% | +0.389% | +3.954% | +6.824% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.642% | -0.096% | +2.693% | +7.684% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.202% | -0.503% | +12.338% | +11.624% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.672% | -0.129% | +7.794% | +11.840% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 1.042% | -1.451% | +4.758% | +13.503% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 1.287% | -0.951% | +9.993% | +12.600% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.966% | -0.553% | +8.637% | +9.386% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.207% | +0.245% | +2.811% | +10.722% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 1.126% | +1.795% | -0.683% | +12.863% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.334% | +1.440% | +7.052% | +11.795% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.054% | -0.560% | +46.427% | +16.562% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.656% | +1.197% | +7.658% | +14.176% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.631% | -1.376% | +16.146% | +13.837% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.471% | -2.192% | +6.614% | +12.826% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.429% | +0.823% | +4.097% | +6.371% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.390% | -1.077% | -1.225% | -2.524% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 1.190% | +0.094% | +4.167% | +9.865% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.618% | -1.264% | +6.449% | +9.345% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.446% | +0.041% | +0.752% | +20.478% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.228% | +0.051% | -0.714% | +22.204% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.920% | -0.260% | +3.076% | +20.709% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.560% | -1.071% | +11.042% | +12.686% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.264% | -0.025% | +0.077% | +10.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.143% | -0.097% | +10.881% | +4.997% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.106% | -0.008% | +2.125% | +5.148% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.083% | -1.216% | +9.236% | +15.342% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 6.051% | +0.998% | +1.500% | +14.147% | +-----+------------------------+--------+------------+------------+------------+ | :-) | regex_dna| 0.234% | +1.939% | -0.414% | +9.866% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.612% | -1.402% | -3.604% | +4.787% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 0.926% | +0.306% | +4.540% | +9.431% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.132% | -1.038% | +7.299% | +17.745% | +-----+------------------------+--------+------------+------------+------------+ | :-( | scimark_fft| 0.504% | -4.220% | -6.594% | +7.644% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.782% | +0.131% | +26.922% | +11.328% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.422% | -0.462% | +4.409% | +3.631% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.617% | -0.731% | +13.099% | +10.579% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 4.049% | -3.334% | -5.358% | +2.318% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 1.592% | -1.617% | +1.414% | +7.731% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.519% | +1.099% | +7.426% | +6.285% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.090% | +0.427% | +7.028% | +3.325% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.201% | +0.583% | +18.777% | +7.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.706% | +0.558% | +11.604% | +7.345% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.253% | -0.385% | +8.998% | +7.633% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.295% | +0.201% | +11.133% | +8.787% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.521% | -0.993% | +9.974% | +10.890% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 7.319% | -0.420% | +19.581% | +15.341% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.245% | -0.365% | +5.566% | +7.060% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.031% | -0.094% | +2.000% | -0.746% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.364% | -1.399% | +6.846% | +20.560% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.215% | +1.985% | -1.518% | +20.630% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.967% | +0.156% | +7.427% | +8.431% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.082% | -0.078% | +5.671% | +10.104% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.573% | +1.413% | +3.566% | +9.217% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 1.875% | +2.399% | -5.528% | +12.109% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.849% | +0.166% | +6.956% | +10.081% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-down-1-up-63-flat-results-for-python-master-branch-2017-12-06 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu Dec 7 01:55:46 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 07 Dec 2017 06:55:46 -0000 Subject: [Python-checkins] Fix hardcoded value in test_os.py (#4744) Message-ID: https://github.com/python/cpython/commit/fb77e0d855e841f42c3fa504efe79eefca9efafb commit: fb77e0d855e841f42c3fa504efe79eefca9efafb branch: master author: Pablo Galindo committer: Victor Stinner date: 2017-12-07T07:55:44+01:00 summary: Fix hardcoded value in test_os.py (#4744) files: M Lib/test/test_os.py diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 96ee3ee577f..22412569092 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1321,7 +1321,7 @@ def get_urandom_subprocess(self, count): 'sys.stdout.buffer.flush()')) out = assert_python_ok('-c', code) stdout = out[1] - self.assertEqual(len(stdout), 16) + self.assertEqual(len(stdout), count) return stdout def test_urandom_subprocess(self): From solipsis at pitrou.net Thu Dec 7 04:12:48 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 07 Dec 2017 09:12:48 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=71 Message-ID: <20171207091248.113835.EF6E24C72B6F7535@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-1, -1, 2] memory blocks, sum=0 test_multiprocessing_spawn leaked [0, 44, 0] references, sum=44 test_multiprocessing_spawn leaked [-1, 22, 0] memory blocks, sum=21 test_multiprocessing_spawn leaked [0, 2, 0] file descriptors, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogCqmuiv', '--timeout', '7200'] From webhook-mailer at python.org Thu Dec 7 06:59:18 2017 From: webhook-mailer at python.org (xdegaye) Date: Thu, 07 Dec 2017 11:59:18 -0000 Subject: [Python-checkins] bpo-32199: The getnode() ip getter now uses 'ip link' instead of 'ip link list' (GH-4696) Message-ID: https://github.com/python/cpython/commit/961dbe0548e26394b7716d41423c61b1e2e58ef7 commit: 961dbe0548e26394b7716d41423c61b1e2e58ef7 branch: master author: xdegaye committer: GitHub date: 2017-12-07T12:59:13+01:00 summary: bpo-32199: The getnode() ip getter now uses 'ip link' instead of 'ip link list' (GH-4696) files: A Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst M Lib/uuid.py diff --git a/Lib/uuid.py b/Lib/uuid.py index be06a6eff3f..b7433cb7192 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -401,7 +401,7 @@ def _ifconfig_getnode(): def _ip_getnode(): """Get the hardware address on Unix by running ip.""" # This works on Linux with iproute2. - mac = _find_mac('ip', 'link list', [b'link/ether'], lambda i: i+1) + mac = _find_mac('ip', 'link', [b'link/ether'], lambda i: i+1) if mac: return mac return None diff --git a/Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst b/Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst new file mode 100644 index 00000000000..d5f88cef5c7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst @@ -0,0 +1 @@ +The getnode() ip getter now uses 'ip link' instead of 'ip link list'. From webhook-mailer at python.org Thu Dec 7 07:48:21 2017 From: webhook-mailer at python.org (xdegaye) Date: Thu, 07 Dec 2017 12:48:21 -0000 Subject: [Python-checkins] bpo-32199: The getnode() ip getter now uses 'ip link' instead of 'ip link list' (GH-4696) (#4747) Message-ID: https://github.com/python/cpython/commit/03031fbc7d44106d652756462db34eae67de9568 commit: 03031fbc7d44106d652756462db34eae67de9568 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: xdegaye date: 2017-12-07T13:48:14+01:00 summary: bpo-32199: The getnode() ip getter now uses 'ip link' instead of 'ip link list' (GH-4696) (#4747) (cherry picked from commit 961dbe0548e26394b7716d41423c61b1e2e58ef7) files: A Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst M Lib/uuid.py diff --git a/Lib/uuid.py b/Lib/uuid.py index 20b02da1ae4..36c956e2b0f 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -358,7 +358,7 @@ def _ifconfig_getnode(): def _ip_getnode(): """Get the hardware address on Unix by running ip.""" # This works on Linux with iproute2. - mac = _find_mac('ip', 'link list', [b'link/ether'], lambda i: i+1) + mac = _find_mac('ip', 'link', [b'link/ether'], lambda i: i+1) if mac: return mac diff --git a/Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst b/Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst new file mode 100644 index 00000000000..d5f88cef5c7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-04-12-23-26.bpo-32199.nGof4v.rst @@ -0,0 +1 @@ +The getnode() ip getter now uses 'ip link' instead of 'ip link list'. From webhook-mailer at python.org Thu Dec 7 13:04:31 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 07 Dec 2017 18:04:31 -0000 Subject: [Python-checkins] bpo-32208: update threading.Semaphore docs and add unit test (#4709) Message-ID: https://github.com/python/cpython/commit/a0374dd34aa25f0895195d388b5ceff43b121b00 commit: a0374dd34aa25f0895195d388b5ceff43b121b00 branch: master author: Garrett Berg committer: Andrew Svetlov date: 2017-12-07T20:04:26+02:00 summary: bpo-32208: update threading.Semaphore docs and add unit test (#4709) * fix issue32208: update threading.Semaphore docs and add unit test to validate correct behavior * add test for blocking * Update threading.rst * semaphore: remove documentation validation tests and move 'return value' test to BaseSemaphore files: M Doc/library/threading.rst M Lib/test/lock_tests.py diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index 95e27cab7c8..b94021b4eb8 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -684,8 +684,8 @@ Semaphores also support the :ref:`context management protocol `. .. class:: Semaphore(value=1) - This class implements semaphore objects. A semaphore manages a counter - representing the number of :meth:`release` calls minus the number of + This class implements semaphore objects. A semaphore manages an atomic + counter representing the number of :meth:`release` calls minus the number of :meth:`acquire` calls, plus an initial value. The :meth:`acquire` method blocks if necessary until it can return without making the counter negative. If not given, *value* defaults to 1. @@ -701,19 +701,19 @@ Semaphores also support the :ref:`context management protocol `. Acquire a semaphore. - When invoked without arguments: if the internal counter is larger than - zero on entry, decrement it by one and return immediately. If it is zero - on entry, block, waiting until some other thread has called - :meth:`~Semaphore.release` to make it larger than zero. This is done - with proper interlocking so that if multiple :meth:`acquire` calls are - blocked, :meth:`~Semaphore.release` will wake exactly one of them up. - The implementation may pick one at random, so the order in which - blocked threads are awakened should not be relied on. Returns - true (or blocks indefinitely). + When invoked without arguments: + + * If the internal counter is larger than zero on entry, decrement it by + one and return true immediately. + * If the internal counter is zero on entry, block until awoken by a call to + :meth:`~Semaphore.release`. Once awoken (and the counter is greater + than 0), decrement the counter by 1 and return true. Exactly one + thread will be awoken by each call to :meth:`~Semaphore.release`. The + order in which threads are awoken should not be relied on. When invoked with *blocking* set to false, do not block. If a call - without an argument would block, return false immediately; otherwise, - do the same thing as when called without arguments, and return true. + without an argument would block, return false immediately; otherwise, do + the same thing as when called without arguments, and return true. When invoked with a *timeout* other than ``None``, it will block for at most *timeout* seconds. If acquire does not complete successfully in diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index a1ea96d42ce..5b1f033c6f8 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -629,13 +629,14 @@ def test_acquire_contended(self): sem = self.semtype(7) sem.acquire() N = 10 + sem_results = [] results1 = [] results2 = [] phase_num = 0 def f(): - sem.acquire() + sem_results.append(sem.acquire()) results1.append(phase_num) - sem.acquire() + sem_results.append(sem.acquire()) results2.append(phase_num) b = Bunch(f, 10) b.wait_for_started() @@ -659,6 +660,7 @@ def f(): # Final release, to let the last thread finish sem.release() b.wait_for_finished() + self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1)) def test_try_acquire(self): sem = self.semtype(2) From webhook-mailer at python.org Thu Dec 7 13:48:38 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 07 Dec 2017 18:48:38 -0000 Subject: [Python-checkins] bpo-32208: update threading.Semaphore docs and add unit test (GH-4709) (#4750) Message-ID: https://github.com/python/cpython/commit/a04ca12e12b522850e7e9244c250754d3cd36f0a commit: a04ca12e12b522850e7e9244c250754d3cd36f0a branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-07T20:48:35+02:00 summary: bpo-32208: update threading.Semaphore docs and add unit test (GH-4709) (#4750) * fix issue32208: update threading.Semaphore docs and add unit test to validate correct behavior * add test for blocking * Update threading.rst * semaphore: remove documentation validation tests and move 'return value' test to BaseSemaphore (cherry picked from commit a0374dd34aa25f0895195d388b5ceff43b121b00) files: M Doc/library/threading.rst M Lib/test/lock_tests.py diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index c375754629e..26e6a35bfba 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -684,8 +684,8 @@ Semaphores also support the :ref:`context management protocol `. .. class:: Semaphore(value=1) - This class implements semaphore objects. A semaphore manages a counter - representing the number of :meth:`release` calls minus the number of + This class implements semaphore objects. A semaphore manages an atomic + counter representing the number of :meth:`release` calls minus the number of :meth:`acquire` calls, plus an initial value. The :meth:`acquire` method blocks if necessary until it can return without making the counter negative. If not given, *value* defaults to 1. @@ -701,19 +701,19 @@ Semaphores also support the :ref:`context management protocol `. Acquire a semaphore. - When invoked without arguments: if the internal counter is larger than - zero on entry, decrement it by one and return immediately. If it is zero - on entry, block, waiting until some other thread has called - :meth:`~Semaphore.release` to make it larger than zero. This is done - with proper interlocking so that if multiple :meth:`acquire` calls are - blocked, :meth:`~Semaphore.release` will wake exactly one of them up. - The implementation may pick one at random, so the order in which - blocked threads are awakened should not be relied on. Returns - true (or blocks indefinitely). + When invoked without arguments: + + * If the internal counter is larger than zero on entry, decrement it by + one and return true immediately. + * If the internal counter is zero on entry, block until awoken by a call to + :meth:`~Semaphore.release`. Once awoken (and the counter is greater + than 0), decrement the counter by 1 and return true. Exactly one + thread will be awoken by each call to :meth:`~Semaphore.release`. The + order in which threads are awoken should not be relied on. When invoked with *blocking* set to false, do not block. If a call - without an argument would block, return false immediately; otherwise, - do the same thing as when called without arguments, and return true. + without an argument would block, return false immediately; otherwise, do + the same thing as when called without arguments, and return true. When invoked with a *timeout* other than ``None``, it will block for at most *timeout* seconds. If acquire does not complete successfully in diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index 4fa154f734d..c1775702487 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -619,13 +619,14 @@ def test_acquire_contended(self): sem = self.semtype(7) sem.acquire() N = 10 + sem_results = [] results1 = [] results2 = [] phase_num = 0 def f(): - sem.acquire() + sem_results.append(sem.acquire()) results1.append(phase_num) - sem.acquire() + sem_results.append(sem.acquire()) results2.append(phase_num) b = Bunch(f, 10) b.wait_for_started() @@ -649,6 +650,7 @@ def f(): # Final release, to let the last thread finish sem.release() b.wait_for_finished() + self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1)) def test_try_acquire(self): sem = self.semtype(2) From webhook-mailer at python.org Thu Dec 7 15:25:42 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 07 Dec 2017 20:25:42 -0000 Subject: [Python-checkins] [2.7] bpo-32186: Release the GIL during fstat and lseek calls (#4651) Message-ID: https://github.com/python/cpython/commit/830daae1c82ed33deef0086b7b6323e5be0b0cc8 commit: 830daae1c82ed33deef0086b7b6323e5be0b0cc8 branch: 2.7 author: Nir Soffer committer: Victor Stinner date: 2017-12-07T21:25:39+01:00 summary: [2.7] bpo-32186: Release the GIL during fstat and lseek calls (#4651) In fileio, there were 3 fstat() calls and one lseek() call that did not release the GIL during the call. This can cause all threads to hang for unlimited time when using io.FileIO with inaccessible NFS server. Same issue seen in fileio exists also in fileobject, fixed in the same way. files: A Misc/NEWS.d/next/Library/2017-11-30-20-33-22.bpo-32186.O42bVe.rst M Modules/_io/fileio.c M Objects/fileobject.c diff --git a/Misc/NEWS.d/next/Library/2017-11-30-20-33-22.bpo-32186.O42bVe.rst b/Misc/NEWS.d/next/Library/2017-11-30-20-33-22.bpo-32186.O42bVe.rst new file mode 100644 index 00000000000..66c4468e80c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-30-20-33-22.bpo-32186.O42bVe.rst @@ -0,0 +1,4 @@ +Creating io.FileIO() and builtin file() objects now release the GIL when +checking the file descriptor. io.FileIO.readall(), io.FileIO.read(), and +file.read() now release the GIL when getting the file size. Fixed hang of all +threads with inaccessible NFS server. Patch by Nir Soffer. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 4a71a57ec0d..2b40ada195a 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -146,9 +146,15 @@ dircheck(fileio* self, PyObject *nameobj) { #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) struct stat buf; + int res; if (self->fd < 0) return 0; - if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) { + + Py_BEGIN_ALLOW_THREADS + res = fstat(self->fd, &buf); + Py_END_ALLOW_THREADS + + if (res == 0 && S_ISDIR(buf.st_mode)) { errno = EISDIR; PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); return -1; @@ -162,17 +168,34 @@ check_fd(int fd) { #if defined(HAVE_FSTAT) struct stat buf; - if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) { - PyObject *exc; - char *msg = strerror(EBADF); - exc = PyObject_CallFunction(PyExc_OSError, "(is)", - EBADF, msg); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); - return -1; + int res; + PyObject *exc; + char *msg; + + if (!_PyVerify_fd(fd)) { + goto badfd; } -#endif + + Py_BEGIN_ALLOW_THREADS + res = fstat(fd, &buf); + Py_END_ALLOW_THREADS + + if (res < 0 && errno == EBADF) { + goto badfd; + } + return 0; + +badfd: + msg = strerror(EBADF); + exc = PyObject_CallFunction(PyExc_OSError, "(is)", + EBADF, msg); + PyErr_SetObject(PyExc_OSError, exc); + Py_XDECREF(exc); + return -1; +#else + return 0; +#endif } @@ -519,9 +542,19 @@ new_buffersize(fileio *self, size_t currentsize) #ifdef HAVE_FSTAT off_t pos, end; struct stat st; - if (fstat(self->fd, &st) == 0) { + int res; + + Py_BEGIN_ALLOW_THREADS + res = fstat(self->fd, &st); + Py_END_ALLOW_THREADS + + if (res == 0) { end = st.st_size; + + Py_BEGIN_ALLOW_THREADS pos = lseek(self->fd, 0L, SEEK_CUR); + Py_END_ALLOW_THREADS + /* Files claiming a size smaller than SMALLCHUNK may actually be streaming pseudo-files. In this case, we apply the more aggressive algorithm below. diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 2f63c374d1e..8d1c5812f0d 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -121,10 +121,15 @@ dircheck(PyFileObject* f) { #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) struct stat buf; + int res; if (f->f_fp == NULL) return f; - if (fstat(fileno(f->f_fp), &buf) == 0 && - S_ISDIR(buf.st_mode)) { + + Py_BEGIN_ALLOW_THREADS + res = fstat(fileno(f->f_fp), &buf); + Py_END_ALLOW_THREADS + + if (res == 0 && S_ISDIR(buf.st_mode)) { char *msg = strerror(EISDIR); PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(isO)", EISDIR, msg, f->f_name); @@ -1010,7 +1015,13 @@ new_buffersize(PyFileObject *f, size_t currentsize) #ifdef HAVE_FSTAT off_t pos, end; struct stat st; - if (fstat(fileno(f->f_fp), &st) == 0) { + int res; + + Py_BEGIN_ALLOW_THREADS + res = fstat(fileno(f->f_fp), &st); + Py_END_ALLOW_THREADS + + if (res == 0) { end = st.st_size; /* The following is not a bug: we really need to call lseek() *and* ftell(). The reason is that some stdio libraries @@ -1021,7 +1032,11 @@ new_buffersize(PyFileObject *f, size_t currentsize) works. We can't use the lseek() value either, because we need to take the amount of buffered data into account. (Yet another reason why stdio stinks. :-) */ + + Py_BEGIN_ALLOW_THREADS pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR); + Py_END_ALLOW_THREADS + if (pos >= 0) { pos = ftell(f->f_fp); } From webhook-mailer at python.org Thu Dec 7 18:06:57 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 07 Dec 2017 23:06:57 -0000 Subject: [Python-checkins] PyLong_FromString(): fix Coverity CID 1424951 (#4738) Message-ID: https://github.com/python/cpython/commit/dd431b32f4a599fff9c9cddfe9d48cc66b347481 commit: dd431b32f4a599fff9c9cddfe9d48cc66b347481 branch: master author: Victor Stinner committer: GitHub date: 2017-12-08T00:06:55+01:00 summary: PyLong_FromString(): fix Coverity CID 1424951 (#4738) Explicitly cast digits (Py_ssize_t) to double to fix the following false-alarm warning from Coverity: "fsize_z = digits * log_base_BASE[base] + 1;" CID 1424951: Incorrect expression (UNINTENDED_INTEGER_DIVISION) Dividing integer expressions "9223372036854775783UL" and "4UL", and then converting the integer quotient to type "double". Any remainder, or fractional part of the quotient, is ignored. files: M Objects/longobject.c diff --git a/Objects/longobject.c b/Objects/longobject.c index a7f496825eb..269d6cdea59 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2267,7 +2267,6 @@ just 1 digit at the start, so that the copying code was exercised for every digit beyond the first. ***/ twodigits c; /* current input character */ - double fsize_z; Py_ssize_t size_z; Py_ssize_t digits = 0; int i; @@ -2331,8 +2330,8 @@ digit beyond the first. * need to initialize z->ob_digit -- no slot is read up before * being stored into. */ - fsize_z = digits * log_base_BASE[base] + 1; - if (fsize_z > MAX_LONG_DIGITS) { + double fsize_z = (double)digits * log_base_BASE[base] + 1.0; + if (fsize_z > (double)MAX_LONG_DIGITS) { /* The same exception as in _PyLong_New(). */ PyErr_SetString(PyExc_OverflowError, "too many digits in integer"); From webhook-mailer at python.org Thu Dec 7 19:25:02 2017 From: webhook-mailer at python.org (Neil Schemenauer) Date: Fri, 08 Dec 2017 00:25:02 -0000 Subject: [Python-checkins] Fix missing DECREF of mod. (#4749) Message-ID: https://github.com/python/cpython/commit/11cc289490b7b275fc0a033e2b376a8d4c780d9b commit: 11cc289490b7b275fc0a033e2b376a8d4c780d9b branch: master author: Neil Schemenauer committer: GitHub date: 2017-12-07T16:24:59-08:00 summary: Fix missing DECREF of mod. (#4749) files: M Python/import.c diff --git a/Python/import.c b/Python/import.c index cc7417ba84e..dc79685abd4 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1735,6 +1735,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } } else { + Py_XDECREF(mod); mod = import_find_and_load(abs_name); if (mod == NULL) { goto error; From lp_benchmark_robot at intel.com Thu Dec 7 21:50:39 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 7 Dec 2017 18:50:39 -0800 Subject: [Python-checkins] [1 down, 1 up, 63 flat] Results for Python (master branch) 2017-12-07 Message-ID: Results for project python/master, build date: 2017-12-07 03:03:09-08:00. - commit: fb77e0d - previous commit: a2a25eb - revision date: 2017-12-07 07:55:44+01:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 1.000% | -0.612% | +4.716% | +8.760% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.178% | -2.339% | +21.888% | +12.050% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.371% | -2.051% | +23.012% | +10.777% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.527% | -2.592% | +21.003% | +11.280% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.319% | +2.229% | +8.068% | +5.214% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.196% | +1.397% | +10.811% | +10.283% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.635% | +0.717% | +7.038% | +10.726% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.489% | +0.688% | +0.420% | +8.303% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.771% | -0.635% | +8.913% | +18.170% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.931% | +2.967% | +11.827% | +13.878% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.066% | -0.118% | +4.467% | +8.397% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.357% | +1.572% | +5.464% | +5.308% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.643% | -0.133% | +2.563% | +6.843% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.292% | +1.582% | +13.725% | +8.429% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.323% | +1.618% | +9.286% | +9.755% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.995% | +0.587% | +5.318% | +12.289% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.481% | +0.465% | +10.411% | +11.693% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.050% | +0.066% | +8.697% | +9.653% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.034% | +0.827% | +3.616% | +8.344% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 2.833% | +1.295% | +0.620% | +12.235% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.414% | -1.009% | +6.114% | +13.830% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.016% | +0.316% | +46.596% | +12.595% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 2.063% | -0.632% | +7.074% | +15.181% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.742% | +0.722% | +16.752% | +13.273% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.874% | -0.785% | +5.881% | +12.764% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 2.421% | +0.416% | +4.496% | +5.816% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.465% | -0.257% | -1.486% | -0.514% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.479% | +0.777% | +4.912% | +7.684% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.542% | -0.152% | +6.307% | +9.934% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.261% | +0.408% | +1.156% | +21.317% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.262% | +1.034% | +0.328% | +20.263% | +-----+------------------------+--------+------------+------------+------------+ | :-( | pickle_list| 0.946% | -3.344% | -0.165% | +22.976% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 6.341% | -1.828% | +9.416% | +11.551% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.264% | +0.224% | +0.301% | +9.755% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.141% | -0.392% | +10.532% | +5.254% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.109% | -0.267% | +1.864% | +5.359% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.873% | +0.176% | +9.396% | +14.192% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 6.227% | -0.899% | +0.614% | +11.914% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.408% | -0.999% | -1.417% | +11.988% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.643% | -2.049% | -5.727% | +7.119% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.646% | -0.537% | +4.028% | +8.786% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.300% | +0.416% | +7.684% | +14.293% | +-----+------------------------+--------+------------+------------+------------+ | :-) | scimark_fft| 1.080% | +3.015% | -3.381% | +4.055% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 2.163% | +0.339% | +27.170% | +7.471% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.162% | +0.153% | +4.555% | +6.410% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.771% | +1.504% | +14.406% | +8.196% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.406% | -0.167% | -5.534% | +2.958% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.370% | +1.806% | +3.194% | +1.092% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.110% | -0.920% | +6.574% | +6.292% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.444% | -0.617% | +6.455% | +5.214% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.638% | +2.339% | +20.677% | +7.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.146% | -0.597% | +11.076% | +8.177% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.761% | +0.278% | +9.252% | +6.474% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.566% | -0.076% | +11.065% | +8.339% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 4.880% | +0.673% | +10.579% | +9.467% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 2.855% | +2.640% | +21.703% | +11.927% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.888% | +0.454% | +5.995% | +6.107% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.472% | -0.897% | +1.121% | +0.441% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.658% | -3.529% | +3.558% | +23.195% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 5.530% | -0.463% | -1.988% | +15.826% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.545% | +0.328% | +7.730% | +6.574% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.055% | -0.045% | +5.628% | +8.648% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.821% | -0.288% | +3.289% | +7.235% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 1.888% | -0.863% | -6.439% | +12.298% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.464% | +0.176% | +7.120% | +8.588% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-down-1-up-63-flat-results-for-python-master-branch-2017-12-07 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From solipsis at pitrou.net Fri Dec 8 04:12:19 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 08 Dec 2017 09:12:19 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=5 Message-ID: <20171208091218.97252.4DA98B5B509B5747@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 7] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [1, 1, -2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogjJdfub', '--timeout', '7200'] From webhook-mailer at python.org Fri Dec 8 07:48:49 2017 From: webhook-mailer at python.org (R. David Murray) Date: Fri, 08 Dec 2017 12:48:49 -0000 Subject: [Python-checkins] bpo-22589 Changed MIME type of .bmp to "image/bmp" (#4756) Message-ID: https://github.com/python/cpython/commit/ede157331b4f9e550334900b3b4de1c8590688de commit: ede157331b4f9e550334900b3b4de1c8590688de branch: master author: Nitish Chandra committer: R. David Murray date: 2017-12-08T07:48:44-05:00 summary: bpo-22589 Changed MIME type of .bmp to "image/bmp" (#4756) Per rfc7903 this is the standard MIME type for this file format, and appears as such in the IANA MIME registry. files: A Misc/NEWS.d/next/Library/2017-12-08-15-09-41.bpo-22589.8ouqI6.rst M Lib/mimetypes.py diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index 44112027cb9..c86dd6d1345 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -410,7 +410,7 @@ def _default_mime_types(): '.bat' : 'text/plain', '.bcpio' : 'application/x-bcpio', '.bin' : 'application/octet-stream', - '.bmp' : 'image/x-ms-bmp', + '.bmp' : 'image/bmp', '.c' : 'text/plain', '.cdf' : 'application/x-netcdf', '.cpio' : 'application/x-cpio', diff --git a/Misc/NEWS.d/next/Library/2017-12-08-15-09-41.bpo-22589.8ouqI6.rst b/Misc/NEWS.d/next/Library/2017-12-08-15-09-41.bpo-22589.8ouqI6.rst new file mode 100644 index 00000000000..e8469cba610 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-08-15-09-41.bpo-22589.8ouqI6.rst @@ -0,0 +1 @@ +Changed MIME type of .bmp from 'image/x-ms-bmp' to 'image/bmp' From webhook-mailer at python.org Fri Dec 8 16:34:20 2017 From: webhook-mailer at python.org (larryhastings) Date: Fri, 08 Dec 2017 21:34:20 -0000 Subject: [Python-checkins] bpo-30657: Fix CVE-2017-1000158 (#4664) Message-ID: https://github.com/python/cpython/commit/fd8614c5c5466a14a945db5b059c10c0fb8f76d9 commit: fd8614c5c5466a14a945db5b059c10c0fb8f76d9 branch: 3.5 author: Miro Hron?ok committer: larryhastings date: 2017-12-08T13:34:12-08:00 summary: bpo-30657: Fix CVE-2017-1000158 (#4664) Fixes possible integer overflow in PyBytes_DecodeEscape. Co-Authored-By: Jay Bosamiya files: A Misc/NEWS.d/next/Security/2017-12-01-18-51-03.bpo-30657.Fd8kId.rst M Misc/ACKS M Objects/bytesobject.c diff --git a/Misc/ACKS b/Misc/ACKS index fbf110d801b..1a35aad66ce 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -167,6 +167,7 @@ M?d?ric Boquien Matias Bordese Jonas Borgstr?m Jurjen Bos +Jay Bosamiya Peter Bosch Dan Boswell Eric Bouck @@ -651,6 +652,7 @@ Ken Howard Brad Howes Mike Hoy Ben Hoyt +Miro Hron?ok Chiu-Hsiang Hsu Chih-Hao Huang Christian Hudon diff --git a/Misc/NEWS.d/next/Security/2017-12-01-18-51-03.bpo-30657.Fd8kId.rst b/Misc/NEWS.d/next/Security/2017-12-01-18-51-03.bpo-30657.Fd8kId.rst new file mode 100644 index 00000000000..75359b6d883 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2017-12-01-18-51-03.bpo-30657.Fd8kId.rst @@ -0,0 +1,2 @@ +Fixed possible integer overflow in PyBytes_DecodeEscape, CVE-2017-1000158. +Original patch by Jay Bosamiya; rebased to Python 3 by Miro Hron?ok. diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 77dd45e84af..9b29dc38b44 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -970,7 +970,13 @@ PyObject *PyBytes_DecodeEscape(const char *s, char *p, *buf; const char *end; PyObject *v; - Py_ssize_t newlen = recode_encoding ? 4*len:len; + Py_ssize_t newlen; + /* Check for integer overflow */ + if (recode_encoding && (len > PY_SSIZE_T_MAX / 4)) { + PyErr_SetString(PyExc_OverflowError, "string is too large"); + return NULL; + } + newlen = recode_encoding ? 4*len:len; v = PyBytes_FromStringAndSize((char *)NULL, newlen); if (v == NULL) return NULL; From webhook-mailer at python.org Fri Dec 8 17:23:53 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Fri, 08 Dec 2017 22:23:53 -0000 Subject: [Python-checkins] bpo-32193: Convert asyncio to async/await usage (#4753) Message-ID: https://github.com/python/cpython/commit/5f841b553814969220b096a2b4f959b7f6fcbaf6 commit: 5f841b553814969220b096a2b4f959b7f6fcbaf6 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-09T00:23:48+02:00 summary: bpo-32193: Convert asyncio to async/await usage (#4753) * Convert asyncio/tasks.py to async/await * Convert asyncio/queues.py to async/await * Convert asyncio/test_utils.py to async/await * Convert asyncio/base_subprocess.py to async/await * Convert asyncio/subprocess.py to async/await * Convert asyncio/streams.py to async/await * Fix comments * Convert asyncio/locks.py to async/await * Convert asyncio.sleep to async def * Add a comment * Add missing news * Convert stubs from AbstrctEventLoop to async functions * Convert subprocess_shell/subprocess_exec * Convert connect_read_pipe/connect_write_pip to async/await syntax * Convert create_datagram_endpoint * Convert create_unix_server/create_unix_connection * Get rid of old style coroutines in unix_events.py * Convert selector_events.py to async/await * Convert wait_closed and create_connection * Drop redundant line * Convert base_events.py * Code cleanup * Drop redundant comments * Fix indentation * Add explicit tests for compatibility between old and new coroutines * Convert windows event loop to use async/await * Fix double awaiting of async function * Convert asyncio/locks.py * Improve docstring * Convert tests to async/await * Convert more tests * Convert more tests * Convert more tests * Convert tests * Improve test files: A Misc/NEWS.d/next/Library/2017-12-08-11-02-26.bpo-32193.NJe_TQ.rst M Lib/asyncio/base_events.py M Lib/asyncio/base_subprocess.py M Lib/asyncio/events.py M Lib/asyncio/locks.py M Lib/asyncio/queues.py M Lib/asyncio/selector_events.py M Lib/asyncio/streams.py M Lib/asyncio/subprocess.py M Lib/asyncio/tasks.py M Lib/asyncio/test_utils.py M Lib/asyncio/unix_events.py M Lib/asyncio/windows_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_locks.py M Lib/test/test_asyncio/test_queues.py M Lib/test/test_asyncio/test_streams.py M Lib/test/test_asyncio/test_subprocess.py M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_asyncio/test_unix_events.py M Lib/test/test_asyncio/test_windows_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index ffdb50f4bee..ab92a0b5807 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -33,7 +33,6 @@ from . import events from . import futures from . import tasks -from .coroutines import coroutine from .log import logger @@ -220,13 +219,12 @@ def _wakeup(self): if not waiter.done(): waiter.set_result(waiter) - @coroutine - def wait_closed(self): + async def wait_closed(self): if self.sockets is None or self._waiters is None: return waiter = self._loop.create_future() self._waiters.append(waiter) - yield from waiter + await waiter class BaseEventLoop(events.AbstractEventLoop): @@ -330,10 +328,9 @@ def _make_write_pipe_transport(self, pipe, protocol, waiter=None, """Create write pipe transport.""" raise NotImplementedError - @coroutine - def _make_subprocess_transport(self, protocol, args, shell, - stdin, stdout, stderr, bufsize, - extra=None, **kwargs): + async def _make_subprocess_transport(self, protocol, args, shell, + stdin, stdout, stderr, bufsize, + extra=None, **kwargs): """Create subprocess transport.""" raise NotImplementedError @@ -371,8 +368,7 @@ def _asyncgen_firstiter_hook(self, agen): self._asyncgens.add(agen) - @coroutine - def shutdown_asyncgens(self): + async def shutdown_asyncgens(self): """Shutdown all active asynchronous generators.""" self._asyncgens_shutdown_called = True @@ -384,12 +380,11 @@ def shutdown_asyncgens(self): closing_agens = list(self._asyncgens) self._asyncgens.clear() - shutdown_coro = tasks.gather( + results = await tasks.gather( *[ag.aclose() for ag in closing_agens], return_exceptions=True, loop=self) - results = yield from shutdown_coro for result, agen in zip(results, closing_agens): if isinstance(result, Exception): self.call_exception_handler({ @@ -671,10 +666,10 @@ def getaddrinfo(self, host, port, *, def getnameinfo(self, sockaddr, flags=0): return self.run_in_executor(None, socket.getnameinfo, sockaddr, flags) - @coroutine - def create_connection(self, protocol_factory, host=None, port=None, *, - ssl=None, family=0, proto=0, flags=0, sock=None, - local_addr=None, server_hostname=None): + async def create_connection(self, protocol_factory, host=None, port=None, + *, ssl=None, family=0, + proto=0, flags=0, sock=None, + local_addr=None, server_hostname=None): """Connect to a TCP server. Create a streaming transport connection to a given Internet host and @@ -722,7 +717,7 @@ def create_connection(self, protocol_factory, host=None, port=None, *, else: f2 = None - yield from tasks.wait(fs, loop=self) + await tasks.wait(fs, loop=self) infos = f1.result() if not infos: @@ -755,7 +750,7 @@ def create_connection(self, protocol_factory, host=None, port=None, *, continue if self._debug: logger.debug("connect %r to %r", sock, address) - yield from self.sock_connect(sock, address) + await self.sock_connect(sock, address) except OSError as exc: if sock is not None: sock.close() @@ -793,7 +788,7 @@ def create_connection(self, protocol_factory, host=None, port=None, *, raise ValueError( 'A Stream Socket was expected, got {!r}'.format(sock)) - transport, protocol = yield from self._create_connection_transport( + transport, protocol = await self._create_connection_transport( sock, protocol_factory, ssl, server_hostname) if self._debug: # Get the socket from the transport because SSL transport closes @@ -803,9 +798,8 @@ def create_connection(self, protocol_factory, host=None, port=None, *, sock, host, port, transport, protocol) return transport, protocol - @coroutine - def _create_connection_transport(self, sock, protocol_factory, ssl, - server_hostname, server_side=False): + async def _create_connection_transport(self, sock, protocol_factory, ssl, + server_hostname, server_side=False): sock.setblocking(False) @@ -820,19 +814,18 @@ def _create_connection_transport(self, sock, protocol_factory, ssl, transport = self._make_socket_transport(sock, protocol, waiter) try: - yield from waiter + await waiter except: transport.close() raise return transport, protocol - @coroutine - def create_datagram_endpoint(self, protocol_factory, - local_addr=None, remote_addr=None, *, - family=0, proto=0, flags=0, - reuse_address=None, reuse_port=None, - allow_broadcast=None, sock=None): + async def create_datagram_endpoint(self, protocol_factory, + local_addr=None, remote_addr=None, *, + family=0, proto=0, flags=0, + reuse_address=None, reuse_port=None, + allow_broadcast=None, sock=None): """Create datagram connection.""" if sock is not None: if not _is_dgram_socket(sock): @@ -872,7 +865,7 @@ def create_datagram_endpoint(self, protocol_factory, assert isinstance(addr, tuple) and len(addr) == 2, ( '2-tuple is expected') - infos = yield from _ensure_resolved( + infos = await _ensure_resolved( addr, family=family, type=socket.SOCK_DGRAM, proto=proto, flags=flags, loop=self) if not infos: @@ -918,7 +911,7 @@ def create_datagram_endpoint(self, protocol_factory, if local_addr: sock.bind(local_address) if remote_addr: - yield from self.sock_connect(sock, remote_address) + await self.sock_connect(sock, remote_address) r_addr = remote_address except OSError as exc: if sock is not None: @@ -948,32 +941,30 @@ def create_datagram_endpoint(self, protocol_factory, remote_addr, transport, protocol) try: - yield from waiter + await waiter except: transport.close() raise return transport, protocol - @coroutine - def _create_server_getaddrinfo(self, host, port, family, flags): - infos = yield from _ensure_resolved((host, port), family=family, - type=socket.SOCK_STREAM, - flags=flags, loop=self) + async def _create_server_getaddrinfo(self, host, port, family, flags): + infos = await _ensure_resolved((host, port), family=family, + type=socket.SOCK_STREAM, + flags=flags, loop=self) if not infos: raise OSError('getaddrinfo({!r}) returned empty list'.format(host)) return infos - @coroutine - def create_server(self, protocol_factory, host=None, port=None, - *, - family=socket.AF_UNSPEC, - flags=socket.AI_PASSIVE, - sock=None, - backlog=100, - ssl=None, - reuse_address=None, - reuse_port=None): + async def create_server(self, protocol_factory, host=None, port=None, + *, + family=socket.AF_UNSPEC, + flags=socket.AI_PASSIVE, + sock=None, + backlog=100, + ssl=None, + reuse_address=None, + reuse_port=None): """Create a TCP server. The host parameter can be a string, in that case the TCP server is bound @@ -1011,7 +1002,7 @@ def create_server(self, protocol_factory, host=None, port=None, fs = [self._create_server_getaddrinfo(host, port, family=family, flags=flags) for host in hosts] - infos = yield from tasks.gather(*fs, loop=self) + infos = await tasks.gather(*fs, loop=self) infos = set(itertools.chain.from_iterable(infos)) completed = False @@ -1068,8 +1059,8 @@ def create_server(self, protocol_factory, host=None, port=None, logger.info("%r is serving", server) return server - @coroutine - def connect_accepted_socket(self, protocol_factory, sock, *, ssl=None): + async def connect_accepted_socket(self, protocol_factory, sock, + *, ssl=None): """Handle an accepted connection. This is used by servers that accept connections outside of @@ -1082,7 +1073,7 @@ def connect_accepted_socket(self, protocol_factory, sock, *, ssl=None): raise ValueError( 'A Stream Socket was expected, got {!r}'.format(sock)) - transport, protocol = yield from self._create_connection_transport( + transport, protocol = await self._create_connection_transport( sock, protocol_factory, ssl, '', server_side=True) if self._debug: # Get the socket from the transport because SSL transport closes @@ -1091,14 +1082,13 @@ def connect_accepted_socket(self, protocol_factory, sock, *, ssl=None): logger.debug("%r handled: (%r, %r)", sock, transport, protocol) return transport, protocol - @coroutine - def connect_read_pipe(self, protocol_factory, pipe): + async def connect_read_pipe(self, protocol_factory, pipe): protocol = protocol_factory() waiter = self.create_future() transport = self._make_read_pipe_transport(pipe, protocol, waiter) try: - yield from waiter + await waiter except: transport.close() raise @@ -1108,14 +1098,13 @@ def connect_read_pipe(self, protocol_factory, pipe): pipe.fileno(), transport, protocol) return transport, protocol - @coroutine - def connect_write_pipe(self, protocol_factory, pipe): + async def connect_write_pipe(self, protocol_factory, pipe): protocol = protocol_factory() waiter = self.create_future() transport = self._make_write_pipe_transport(pipe, protocol, waiter) try: - yield from waiter + await waiter except: transport.close() raise @@ -1138,11 +1127,13 @@ def _log_subprocess(self, msg, stdin, stdout, stderr): info.append('stderr=%s' % _format_pipe(stderr)) logger.debug(' '.join(info)) - @coroutine - def subprocess_shell(self, protocol_factory, cmd, *, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=False, shell=True, bufsize=0, - **kwargs): + async def subprocess_shell(self, protocol_factory, cmd, *, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=False, + shell=True, bufsize=0, + **kwargs): if not isinstance(cmd, (bytes, str)): raise ValueError("cmd must be a string") if universal_newlines: @@ -1157,17 +1148,16 @@ def subprocess_shell(self, protocol_factory, cmd, *, stdin=subprocess.PIPE, # (password) and may be too long debug_log = 'run shell command %r' % cmd self._log_subprocess(debug_log, stdin, stdout, stderr) - transport = yield from self._make_subprocess_transport( + transport = await self._make_subprocess_transport( protocol, cmd, True, stdin, stdout, stderr, bufsize, **kwargs) if self._debug: logger.info('%s: %r', debug_log, transport) return transport, protocol - @coroutine - def subprocess_exec(self, protocol_factory, program, *args, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, universal_newlines=False, - shell=False, bufsize=0, **kwargs): + async def subprocess_exec(self, protocol_factory, program, *args, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=False, + shell=False, bufsize=0, **kwargs): if universal_newlines: raise ValueError("universal_newlines must be False") if shell: @@ -1186,7 +1176,7 @@ def subprocess_exec(self, protocol_factory, program, *args, # (password) and may be too long debug_log = 'execute program %r' % program self._log_subprocess(debug_log, stdin, stdout, stderr) - transport = yield from self._make_subprocess_transport( + transport = await self._make_subprocess_transport( protocol, popen_args, False, stdin, stdout, stderr, bufsize, **kwargs) if self._debug: diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index cac8d962c0b..7e5a901845d 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -4,7 +4,6 @@ from . import protocols from . import transports -from .coroutines import coroutine from .log import logger @@ -154,26 +153,25 @@ def kill(self): self._check_proc() self._proc.kill() - @coroutine - def _connect_pipes(self, waiter): + async def _connect_pipes(self, waiter): try: proc = self._proc loop = self._loop if proc.stdin is not None: - _, pipe = yield from loop.connect_write_pipe( + _, pipe = await loop.connect_write_pipe( lambda: WriteSubprocessPipeProto(self, 0), proc.stdin) self._pipes[0] = pipe if proc.stdout is not None: - _, pipe = yield from loop.connect_read_pipe( + _, pipe = await loop.connect_read_pipe( lambda: ReadSubprocessPipeProto(self, 1), proc.stdout) self._pipes[1] = pipe if proc.stderr is not None: - _, pipe = yield from loop.connect_read_pipe( + _, pipe = await loop.connect_read_pipe( lambda: ReadSubprocessPipeProto(self, 2), proc.stderr) self._pipes[2] = pipe @@ -224,8 +222,7 @@ def _process_exited(self, returncode): waiter.set_result(returncode) self._exit_waiters = None - @coroutine - def _wait(self): + async def _wait(self): """Wait until the process exit and return the process return code. This method is a coroutine.""" @@ -234,7 +231,7 @@ def _wait(self): waiter = self._loop.create_future() self._exit_waiters.append(waiter) - return (yield from waiter) + return await waiter def _try_finish(self): assert not self._finished diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index e59d3d2760e..2cd6035973d 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -219,7 +219,7 @@ def close(self): """Stop serving. This leaves existing connections open.""" return NotImplemented - def wait_closed(self): + async def wait_closed(self): """Coroutine to wait until service is closed.""" return NotImplemented @@ -267,7 +267,7 @@ def close(self): """ raise NotImplementedError - def shutdown_asyncgens(self): + async def shutdown_asyncgens(self): """Shutdown all active asynchronous generators.""" raise NotImplementedError @@ -302,7 +302,7 @@ def create_task(self, coro): def call_soon_threadsafe(self, callback, *args): raise NotImplementedError - def run_in_executor(self, executor, func, *args): + async def run_in_executor(self, executor, func, *args): raise NotImplementedError def set_default_executor(self, executor): @@ -310,21 +310,23 @@ def set_default_executor(self, executor): # Network I/O methods returning Futures. - def getaddrinfo(self, host, port, *, family=0, type=0, proto=0, flags=0): + async def getaddrinfo(self, host, port, *, + family=0, type=0, proto=0, flags=0): raise NotImplementedError - def getnameinfo(self, sockaddr, flags=0): + async def getnameinfo(self, sockaddr, flags=0): raise NotImplementedError - def create_connection(self, protocol_factory, host=None, port=None, *, - ssl=None, family=0, proto=0, flags=0, sock=None, - local_addr=None, server_hostname=None): + async def create_connection(self, protocol_factory, host=None, port=None, + *, ssl=None, family=0, proto=0, + flags=0, sock=None, local_addr=None, + server_hostname=None): raise NotImplementedError - def create_server(self, protocol_factory, host=None, port=None, *, - family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, - sock=None, backlog=100, ssl=None, reuse_address=None, - reuse_port=None): + async def create_server(self, protocol_factory, host=None, port=None, + *, family=socket.AF_UNSPEC, + flags=socket.AI_PASSIVE, sock=None, backlog=100, + ssl=None, reuse_address=None, reuse_port=None): """A coroutine which creates a TCP server bound to host and port. The return value is a Server object which can be used to stop @@ -362,13 +364,13 @@ def create_server(self, protocol_factory, host=None, port=None, *, """ raise NotImplementedError - def create_unix_connection(self, protocol_factory, path=None, *, - ssl=None, sock=None, - server_hostname=None): + async def create_unix_connection(self, protocol_factory, path=None, *, + ssl=None, sock=None, + server_hostname=None): raise NotImplementedError - def create_unix_server(self, protocol_factory, path=None, *, - sock=None, backlog=100, ssl=None): + async def create_unix_server(self, protocol_factory, path=None, *, + sock=None, backlog=100, ssl=None): """A coroutine which creates a UNIX Domain Socket server. The return value is a Server object, which can be used to stop @@ -388,11 +390,11 @@ def create_unix_server(self, protocol_factory, path=None, *, """ raise NotImplementedError - def create_datagram_endpoint(self, protocol_factory, - local_addr=None, remote_addr=None, *, - family=0, proto=0, flags=0, - reuse_address=None, reuse_port=None, - allow_broadcast=None, sock=None): + async def create_datagram_endpoint(self, protocol_factory, + local_addr=None, remote_addr=None, *, + family=0, proto=0, flags=0, + reuse_address=None, reuse_port=None, + allow_broadcast=None, sock=None): """A coroutine which creates a datagram endpoint. This method will try to establish the endpoint in the background. @@ -425,7 +427,7 @@ def create_datagram_endpoint(self, protocol_factory, # Pipes and subprocesses. - def connect_read_pipe(self, protocol_factory, pipe): + async def connect_read_pipe(self, protocol_factory, pipe): """Register read pipe in event loop. Set the pipe to non-blocking mode. protocol_factory should instantiate object with Protocol interface. @@ -438,7 +440,7 @@ def connect_read_pipe(self, protocol_factory, pipe): # close fd in pipe transport then close f and vise versa. raise NotImplementedError - def connect_write_pipe(self, protocol_factory, pipe): + async def connect_write_pipe(self, protocol_factory, pipe): """Register write pipe in event loop. protocol_factory should instantiate object with BaseProtocol interface. @@ -451,14 +453,18 @@ def connect_write_pipe(self, protocol_factory, pipe): # close fd in pipe transport then close f and vise versa. raise NotImplementedError - def subprocess_shell(self, protocol_factory, cmd, *, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - **kwargs): + async def subprocess_shell(self, protocol_factory, cmd, *, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + **kwargs): raise NotImplementedError - def subprocess_exec(self, protocol_factory, *args, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - **kwargs): + async def subprocess_exec(self, protocol_factory, *args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + **kwargs): raise NotImplementedError # Ready-based callback registration methods. @@ -480,19 +486,19 @@ def remove_writer(self, fd): # Completion based I/O methods returning Futures. - def sock_recv(self, sock, nbytes): + async def sock_recv(self, sock, nbytes): raise NotImplementedError - def sock_recv_into(self, sock, buf): + async def sock_recv_into(self, sock, buf): raise NotImplementedError - def sock_sendall(self, sock, data): + async def sock_sendall(self, sock, data): raise NotImplementedError - def sock_connect(self, sock, address): + async def sock_connect(self, sock, address): raise NotImplementedError - def sock_accept(self, sock): + async def sock_accept(self, sock): raise NotImplementedError # Signal handling. diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 750c4359179..aa6ed3eaea6 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -66,20 +66,21 @@ def __iter__(self): yield from self.acquire() return _ContextManager(self) + async def __acquire_ctx(self): + await self.acquire() + return _ContextManager(self) + def __await__(self): # To make "with await lock" work. - yield from self.acquire() - return _ContextManager(self) + return self.__acquire_ctx().__await__() - @coroutine - def __aenter__(self): - yield from self.acquire() + async def __aenter__(self): + await 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): + async def __aexit__(self, exc_type, exc, tb): self.release() @@ -156,8 +157,7 @@ def locked(self): """Return True if lock is acquired.""" return self._locked - @coroutine - def acquire(self): + async def acquire(self): """Acquire a lock. This method blocks until the lock is unlocked, then sets it to @@ -170,7 +170,7 @@ def acquire(self): fut = self._loop.create_future() self._waiters.append(fut) try: - yield from fut + await fut self._locked = True return True except futures.CancelledError: @@ -251,8 +251,7 @@ def clear(self): to true again.""" self._value = False - @coroutine - def wait(self): + async def wait(self): """Block until the internal flag is true. If the internal flag is true on entry, return True @@ -265,7 +264,7 @@ def wait(self): fut = self._loop.create_future() self._waiters.append(fut) try: - yield from fut + await fut return True finally: self._waiters.remove(fut) @@ -307,8 +306,7 @@ def __repr__(self): extra = '{},waiters:{}'.format(extra, len(self._waiters)) return '<{} [{}]>'.format(res[1:-1], extra) - @coroutine - def wait(self): + async def wait(self): """Wait until notified. If the calling coroutine has not acquired the lock when this @@ -327,7 +325,7 @@ def wait(self): fut = self._loop.create_future() self._waiters.append(fut) try: - yield from fut + await fut return True finally: self._waiters.remove(fut) @@ -336,13 +334,12 @@ def wait(self): # Must reacquire lock even if wait is cancelled while True: try: - yield from self.acquire() + await self.acquire() break except futures.CancelledError: pass - @coroutine - def wait_for(self, predicate): + async def wait_for(self, predicate): """Wait until a predicate becomes true. The predicate should be a callable which result will be @@ -351,7 +348,7 @@ def wait_for(self, predicate): """ result = predicate() while not result: - yield from self.wait() + await self.wait() result = predicate() return result @@ -432,8 +429,7 @@ def locked(self): """Returns True if semaphore can not be acquired immediately.""" return self._value == 0 - @coroutine - def acquire(self): + async def acquire(self): """Acquire a semaphore. If the internal counter is larger than zero on entry, @@ -446,7 +442,7 @@ def acquire(self): fut = self._loop.create_future() self._waiters.append(fut) try: - yield from fut + await fut except: # See the similar code in Queue.get. fut.cancel() diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py index 4fc681dde97..10e694f1393 100644 --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -7,7 +7,6 @@ from . import events from . import locks -from .coroutines import coroutine class QueueEmpty(Exception): @@ -28,7 +27,7 @@ class Queue: """A queue, useful for coordinating producer and consumer coroutines. If maxsize is less than or equal to zero, the queue size is infinite. If it - is an integer greater than 0, then "yield from put()" will block when the + is an integer greater than 0, then "await put()" will block when the queue reaches maxsize, until an item is removed by get(). Unlike the standard library Queue, you can reliably know this Queue's size @@ -116,20 +115,17 @@ def full(self): else: return self.qsize() >= self._maxsize - @coroutine - def put(self, item): + async def put(self, item): """Put an item into the queue. Put an item into the queue. If the queue is full, wait until a free slot is available before adding item. - - This method is a coroutine. """ while self.full(): putter = self._loop.create_future() self._putters.append(putter) try: - yield from putter + await putter except: putter.cancel() # Just in case putter is not done yet. if not self.full() and not putter.cancelled(): @@ -151,19 +147,16 @@ def put_nowait(self, item): self._finished.clear() self._wakeup_next(self._getters) - @coroutine - def get(self): + async def get(self): """Remove and return an item from the queue. If queue is empty, wait until an item is available. - - This method is a coroutine. """ while self.empty(): getter = self._loop.create_future() self._getters.append(getter) try: - yield from getter + await getter except: getter.cancel() # Just in case getter is not done yet. @@ -210,8 +203,7 @@ def task_done(self): if self._unfinished_tasks == 0: self._finished.set() - @coroutine - def join(self): + async def join(self): """Block until all items in the queue have been gotten and processed. The count of unfinished tasks goes up whenever an item is added to the @@ -220,7 +212,7 @@ def join(self): When the count of unfinished tasks drops to zero, join() unblocks. """ if self._unfinished_tasks > 0: - yield from self._finished.wait() + await self._finished.wait() class PriorityQueue(Queue): diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 3639466f6c2..c30fde7f4da 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -24,7 +24,6 @@ from . import futures from . import transports from . import sslproto -from .coroutines import coroutine from .log import logger @@ -189,9 +188,8 @@ def _accept_connection(self, protocol_factory, sock, sslcontext, server) self.create_task(accept) - @coroutine - def _accept_connection2(self, protocol_factory, conn, extra, - sslcontext=None, server=None): + async def _accept_connection2(self, protocol_factory, conn, extra, + sslcontext=None, server=None): protocol = None transport = None try: @@ -207,7 +205,7 @@ def _accept_connection2(self, protocol_factory, conn, extra, server=server) try: - yield from waiter + await waiter except: transport.close() raise @@ -452,8 +450,7 @@ def _sock_sendall(self, fut, registered_fd, sock, data): fd = sock.fileno() self.add_writer(fd, self._sock_sendall, fut, fd, sock, data) - @coroutine - def sock_connect(self, sock, address): + async def sock_connect(self, sock, address): """Connect to a remote socket at address. This method is a coroutine. @@ -465,12 +462,12 @@ def sock_connect(self, sock, address): resolved = base_events._ensure_resolved( address, family=sock.family, proto=sock.proto, loop=self) if not resolved.done(): - yield from resolved + await resolved _, _, _, _, address = resolved.result()[0] fut = self.create_future() self._sock_connect(fut, sock, address) - return (yield from fut) + return await fut def _sock_connect(self, fut, sock, address): fd = sock.fileno() diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 15c9513527f..baa9ec94439 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -14,8 +14,8 @@ from . import coroutines from . import events from . import protocols -from .coroutines import coroutine from .log import logger +from .tasks import sleep _DEFAULT_LIMIT = 2 ** 16 @@ -52,9 +52,8 @@ def __reduce__(self): return type(self), (self.args[0], self.consumed) - at coroutine -def open_connection(host=None, port=None, *, - loop=None, limit=_DEFAULT_LIMIT, **kwds): +async def open_connection(host=None, port=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): """A wrapper for create_connection() returning a (reader, writer) pair. The reader returned is a StreamReader instance; the writer is a @@ -76,15 +75,14 @@ def open_connection(host=None, port=None, *, loop = events.get_event_loop() reader = StreamReader(limit=limit, loop=loop) protocol = StreamReaderProtocol(reader, loop=loop) - transport, _ = yield from loop.create_connection( + transport, _ = await loop.create_connection( lambda: protocol, host, port, **kwds) writer = StreamWriter(transport, protocol, reader, loop) return reader, writer - at coroutine -def start_server(client_connected_cb, host=None, port=None, *, - loop=None, limit=_DEFAULT_LIMIT, **kwds): +async def start_server(client_connected_cb, host=None, port=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): """Start a socket server, call back for each client connected. The first parameter, `client_connected_cb`, takes two parameters: @@ -115,28 +113,26 @@ def factory(): loop=loop) return protocol - return (yield from loop.create_server(factory, host, port, **kwds)) + return await loop.create_server(factory, host, port, **kwds) if hasattr(socket, 'AF_UNIX'): # UNIX Domain Sockets are supported on this platform - @coroutine - def open_unix_connection(path=None, *, - loop=None, limit=_DEFAULT_LIMIT, **kwds): + async def open_unix_connection(path=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): """Similar to `open_connection` but works with UNIX Domain Sockets.""" if loop is None: loop = events.get_event_loop() reader = StreamReader(limit=limit, loop=loop) protocol = StreamReaderProtocol(reader, loop=loop) - transport, _ = yield from loop.create_unix_connection( + transport, _ = await loop.create_unix_connection( lambda: protocol, path, **kwds) writer = StreamWriter(transport, protocol, reader, loop) return reader, writer - @coroutine - def start_unix_server(client_connected_cb, path=None, *, - loop=None, limit=_DEFAULT_LIMIT, **kwds): + async def start_unix_server(client_connected_cb, path=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): """Similar to `start_server` but works with UNIX Domain Sockets.""" if loop is None: loop = events.get_event_loop() @@ -147,7 +143,7 @@ def factory(): loop=loop) return protocol - return (yield from loop.create_unix_server(factory, path, **kwds)) + return await loop.create_unix_server(factory, path, **kwds) class FlowControlMixin(protocols.Protocol): @@ -203,8 +199,7 @@ def connection_lost(self, exc): else: waiter.set_exception(exc) - @coroutine - def _drain_helper(self): + async def _drain_helper(self): if self._connection_lost: raise ConnectionResetError('Connection lost') if not self._paused: @@ -213,7 +208,7 @@ def _drain_helper(self): assert waiter is None or waiter.cancelled() waiter = self._loop.create_future() self._drain_waiter = waiter - yield from waiter + await waiter class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): @@ -313,14 +308,13 @@ def close(self): def get_extra_info(self, name, default=None): return self._transport.get_extra_info(name, default) - @coroutine - def drain(self): + async def drain(self): """Flush the write buffer. The intended use is to write w.write(data) - yield from w.drain() + await w.drain() """ if self._reader is not None: exc = self._reader.exception() @@ -331,11 +325,11 @@ def drain(self): # Yield to the event loop so connection_lost() may be # called. Without this, _drain_helper() would return # immediately, and code that calls - # write(...); yield from drain() + # write(...); await drain() # in a loop would never call connection_lost(), so it # would not see an error when the socket is closed. - yield - yield from self._protocol._drain_helper() + await sleep(0, loop=self._loop) + await self._protocol._drain_helper() class StreamReader: @@ -436,8 +430,7 @@ def feed_data(self, data): else: self._paused = True - @coroutine - def _wait_for_data(self, func_name): + async def _wait_for_data(self, func_name): """Wait until feed_data() or feed_eof() is called. If stream was paused, automatically resume it. @@ -460,12 +453,11 @@ def _wait_for_data(self, func_name): self._waiter = self._loop.create_future() try: - yield from self._waiter + await self._waiter finally: self._waiter = None - @coroutine - def readline(self): + async def readline(self): """Read chunk of data from the stream until newline (b'\n') is found. On success, return chunk that ends with newline. If only partial @@ -484,7 +476,7 @@ def readline(self): sep = b'\n' seplen = len(sep) try: - line = yield from self.readuntil(sep) + line = await self.readuntil(sep) except IncompleteReadError as e: return e.partial except LimitOverrunError as e: @@ -496,8 +488,7 @@ def readline(self): raise ValueError(e.args[0]) return line - @coroutine - def readuntil(self, separator=b'\n'): + async def readuntil(self, separator=b'\n'): """Read data from the stream until ``separator`` is found. On success, the data and separator will be removed from the @@ -577,7 +568,7 @@ def readuntil(self, separator=b'\n'): raise IncompleteReadError(chunk, None) # _wait_for_data() will resume reading if stream was paused. - yield from self._wait_for_data('readuntil') + await self._wait_for_data('readuntil') if isep > self._limit: raise LimitOverrunError( @@ -588,8 +579,7 @@ def readuntil(self, separator=b'\n'): self._maybe_resume_transport() return bytes(chunk) - @coroutine - def read(self, n=-1): + async def read(self, n=-1): """Read up to `n` bytes from the stream. If n is not provided, or set to -1, read until EOF and return all read @@ -623,14 +613,14 @@ def read(self, n=-1): # bytes. So just call self.read(self._limit) until EOF. blocks = [] while True: - block = yield from self.read(self._limit) + block = await self.read(self._limit) if not block: break blocks.append(block) return b''.join(blocks) if not self._buffer and not self._eof: - yield from self._wait_for_data('read') + await self._wait_for_data('read') # This will work right even if buffer is less than n bytes data = bytes(self._buffer[:n]) @@ -639,8 +629,7 @@ def read(self, n=-1): self._maybe_resume_transport() return data - @coroutine - def readexactly(self, n): + async def readexactly(self, n): """Read exactly `n` bytes. Raise an IncompleteReadError if EOF is reached before `n` bytes can be @@ -670,7 +659,7 @@ def readexactly(self, n): self._buffer.clear() raise IncompleteReadError(incomplete, n) - yield from self._wait_for_data('readexactly') + await self._wait_for_data('readexactly') if len(self._buffer) == n: data = bytes(self._buffer) @@ -684,9 +673,8 @@ def readexactly(self, n): def __aiter__(self): return self - @coroutine - def __anext__(self): - val = yield from self.readline() + async def __anext__(self): + val = await self.readline() if val == b'': raise StopAsyncIteration return val diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py index 4c85466859f..dd3d10c8879 100644 --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -6,7 +6,6 @@ from . import protocols from . import streams from . import tasks -from .coroutines import coroutine from .log import logger @@ -121,12 +120,9 @@ def __repr__(self): def returncode(self): return self._transport.get_returncode() - @coroutine - def wait(self): - """Wait until the process exit and return the process return code. - - This method is a coroutine.""" - return (yield from self._transport._wait()) + async def wait(self): + """Wait until the process exit and return the process return code.""" + return await self._transport._wait() def send_signal(self, signal): self._transport.send_signal(signal) @@ -137,15 +133,14 @@ def terminate(self): def kill(self): self._transport.kill() - @coroutine - def _feed_stdin(self, input): + async def _feed_stdin(self, input): debug = self._loop.get_debug() self.stdin.write(input) if debug: logger.debug('%r communicate: feed stdin (%s bytes)', self, len(input)) try: - yield from self.stdin.drain() + await self.stdin.drain() except (BrokenPipeError, ConnectionResetError) as exc: # communicate() ignores BrokenPipeError and ConnectionResetError if debug: @@ -155,12 +150,10 @@ def _feed_stdin(self, input): logger.debug('%r communicate: close stdin', self) self.stdin.close() - @coroutine - def _noop(self): + async def _noop(self): return None - @coroutine - def _read_stream(self, fd): + async def _read_stream(self, fd): transport = self._transport.get_pipe_transport(fd) if fd == 2: stream = self.stderr @@ -170,15 +163,14 @@ def _read_stream(self, fd): if self._loop.get_debug(): name = 'stdout' if fd == 1 else 'stderr' logger.debug('%r communicate: read %s', self, name) - output = yield from stream.read() + output = await stream.read() if self._loop.get_debug(): name = 'stdout' if fd == 1 else 'stderr' logger.debug('%r communicate: close %s', self, name) transport.close() return output - @coroutine - def communicate(self, input=None): + async def communicate(self, input=None): if input is not None: stdin = self._feed_stdin(input) else: @@ -191,36 +183,36 @@ def communicate(self, input=None): stderr = self._read_stream(2) else: stderr = self._noop() - stdin, stdout, stderr = yield from tasks.gather(stdin, stdout, stderr, - loop=self._loop) - yield from self.wait() + stdin, stdout, stderr = await tasks.gather(stdin, stdout, stderr, + loop=self._loop) + await self.wait() return (stdout, stderr) - at coroutine -def create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, - loop=None, limit=streams._DEFAULT_LIMIT, **kwds): +async def create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, + loop=None, limit=streams._DEFAULT_LIMIT, + **kwds): if loop is None: loop = events.get_event_loop() protocol_factory = lambda: SubprocessStreamProtocol(limit=limit, loop=loop) - transport, protocol = yield from loop.subprocess_shell( - protocol_factory, - cmd, stdin=stdin, stdout=stdout, - stderr=stderr, **kwds) + transport, protocol = await loop.subprocess_shell( + protocol_factory, + cmd, stdin=stdin, stdout=stdout, + stderr=stderr, **kwds) return Process(transport, protocol, loop) - at coroutine -def create_subprocess_exec(program, *args, stdin=None, stdout=None, - stderr=None, loop=None, - limit=streams._DEFAULT_LIMIT, **kwds): + +async def create_subprocess_exec(program, *args, stdin=None, stdout=None, + stderr=None, loop=None, + limit=streams._DEFAULT_LIMIT, **kwds): if loop is None: loop = events.get_event_loop() protocol_factory = lambda: SubprocessStreamProtocol(limit=limit, loop=loop) - transport, protocol = yield from loop.subprocess_exec( - protocol_factory, - program, *args, - stdin=stdin, stdout=stdout, - stderr=stderr, **kwds) + transport, protocol = await loop.subprocess_exec( + protocol_factory, + program, *args, + stdin=stdin, stdout=stdout, + stderr=stderr, **kwds) return Process(transport, protocol, loop) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 5d744c3d30e..c23d06afd7c 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -9,6 +9,7 @@ import concurrent.futures import functools import inspect +import types import warnings import weakref @@ -276,8 +277,7 @@ def _wakeup(self, future): ALL_COMPLETED = concurrent.futures.ALL_COMPLETED - at coroutine -def wait(fs, *, loop=None, timeout=None, return_when=ALL_COMPLETED): +async def wait(fs, *, loop=None, timeout=None, return_when=ALL_COMPLETED): """Wait for the Futures and coroutines given by fs to complete. The sequence futures must not be empty. @@ -288,7 +288,7 @@ def wait(fs, *, loop=None, timeout=None, return_when=ALL_COMPLETED): Usage: - done, pending = yield from asyncio.wait(fs) + done, pending = await asyncio.wait(fs) Note: This does not raise TimeoutError! Futures that aren't done when the timeout occurs are returned in the second set. @@ -305,7 +305,7 @@ def wait(fs, *, loop=None, timeout=None, return_when=ALL_COMPLETED): fs = {ensure_future(f, loop=loop) for f in set(fs)} - return (yield from _wait(fs, timeout, return_when, loop)) + return await _wait(fs, timeout, return_when, loop) def _release_waiter(waiter, *args): @@ -313,8 +313,7 @@ def _release_waiter(waiter, *args): waiter.set_result(None) - at coroutine -def wait_for(fut, timeout, *, loop=None): +async def wait_for(fut, timeout, *, loop=None): """Wait for the single Future or coroutine to complete, with timeout. Coroutine will be wrapped in Task. @@ -331,7 +330,7 @@ def wait_for(fut, timeout, *, loop=None): loop = events.get_event_loop() if timeout is None: - return (yield from fut) + return await fut if timeout <= 0: fut = ensure_future(fut, loop=loop) @@ -352,7 +351,7 @@ def wait_for(fut, timeout, *, loop=None): try: # wait until the future completes or the timeout try: - yield from waiter + await waiter except futures.CancelledError: fut.remove_done_callback(cb) fut.cancel() @@ -368,8 +367,7 @@ def wait_for(fut, timeout, *, loop=None): timeout_handle.cancel() - at coroutine -def _wait(fs, timeout, return_when, loop): +async def _wait(fs, timeout, return_when, loop): """Internal helper for wait() and wait_for(). The fs argument must be a collection of Futures. @@ -397,7 +395,7 @@ def _on_completion(f): f.add_done_callback(_on_completion) try: - yield from waiter + await waiter finally: if timeout_handle is not None: timeout_handle.cancel() @@ -423,10 +421,10 @@ def as_completed(fs, *, loop=None, timeout=None): This differs from PEP 3148; the proper way to use this is: for f in as_completed(fs): - result = yield from f # The 'yield from' may raise. + result = await f # The 'await' may raise. # Use result. - If a timeout is specified, the 'yield from' will raise + If a timeout is specified, the 'await' will raise TimeoutError when the timeout occurs before all Futures are done. Note: The futures 'f' are not necessarily members of fs. @@ -453,9 +451,8 @@ def _on_completion(f): if not todo and timeout_handle is not None: timeout_handle.cancel() - @coroutine - def _wait_for_one(): - f = yield from done.get() + async def _wait_for_one(): + f = await done.get() if f is None: # Dummy value from _on_timeout(). raise futures.TimeoutError @@ -469,11 +466,22 @@ def _wait_for_one(): yield _wait_for_one() - at coroutine -def sleep(delay, result=None, *, loop=None): + at types.coroutine +def __sleep0(): + """Skip one event loop run cycle. + + This is a private helper for 'asyncio.sleep()', used + when the 'delay' is set to 0. It uses a bare 'yield' + expression (which Task._step knows how to handle) + instead of creating a Future object. + """ + yield + + +async def sleep(delay, result=None, *, loop=None): """Coroutine that completes after a given time (in seconds).""" if delay == 0: - yield + await __sleep0() return result if loop is None: @@ -483,7 +491,7 @@ def sleep(delay, result=None, *, loop=None): futures._set_result_unless_cancelled, future, result) try: - return (yield from future) + return await future finally: h.cancel() @@ -652,11 +660,11 @@ def shield(arg, *, loop=None): The statement - res = yield from shield(something()) + res = await shield(something()) is exactly equivalent to the statement - res = yield from something() + res = await something() *except* that if the coroutine containing it is cancelled, the task running in something() is not cancelled. From the POV of @@ -669,7 +677,7 @@ def shield(arg, *, loop=None): you can combine shield() with a try/except clause, as follows: try: - res = yield from shield(something()) + res = await shield(something()) except CancelledError: res = None """ diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py index 32d3b0bf630..231916970c7 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -30,7 +30,6 @@ from . import events from . import futures from . import tasks -from .coroutines import coroutine from .log import logger from test import support @@ -43,8 +42,7 @@ def dummy_ssl_context(): def run_briefly(loop): - @coroutine - def once(): + async def once(): pass gen = once() t = loop.create_task(gen) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index ab818da1dfa..0308b02a52d 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -20,7 +20,6 @@ from . import futures from . import selector_events from . import transports -from .coroutines import coroutine from .log import logger @@ -168,10 +167,9 @@ def _make_write_pipe_transport(self, pipe, protocol, waiter=None, extra=None): return _UnixWritePipeTransport(self, pipe, protocol, waiter, extra) - @coroutine - def _make_subprocess_transport(self, protocol, args, shell, - stdin, stdout, stderr, bufsize, - extra=None, **kwargs): + async def _make_subprocess_transport(self, protocol, args, shell, + stdin, stdout, stderr, bufsize, + extra=None, **kwargs): with events.get_child_watcher() as watcher: waiter = self.create_future() transp = _UnixSubprocessTransport(self, protocol, args, shell, @@ -182,29 +180,20 @@ def _make_subprocess_transport(self, protocol, args, shell, watcher.add_child_handler(transp.get_pid(), self._child_watcher_callback, transp) try: - yield from waiter - except Exception as exc: - # Workaround CPython bug #23353: using yield/yield-from in an - # except block of a generator doesn't clear properly - # sys.exc_info() - err = exc - else: - err = None - - if err is not None: + await waiter + except Exception: transp.close() - yield from transp._wait() - raise err + await transp._wait() + raise return transp def _child_watcher_callback(self, pid, returncode, transp): self.call_soon_threadsafe(transp._process_exited, returncode) - @coroutine - def create_unix_connection(self, protocol_factory, path=None, *, - ssl=None, sock=None, - server_hostname=None): + async def create_unix_connection(self, protocol_factory, path=None, *, + ssl=None, sock=None, + server_hostname=None): assert server_hostname is None or isinstance(server_hostname, str) if ssl: if server_hostname is None: @@ -223,7 +212,7 @@ def create_unix_connection(self, protocol_factory, path=None, *, sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) try: sock.setblocking(False) - yield from self.sock_connect(sock, path) + await self.sock_connect(sock, path) except: sock.close() raise @@ -238,13 +227,12 @@ def create_unix_connection(self, protocol_factory, path=None, *, .format(sock)) sock.setblocking(False) - transport, protocol = yield from self._create_connection_transport( + transport, protocol = await self._create_connection_transport( sock, protocol_factory, ssl, server_hostname) return transport, protocol - @coroutine - def create_unix_server(self, protocol_factory, path=None, *, - sock=None, backlog=100, ssl=None): + async def create_unix_server(self, protocol_factory, path=None, *, + sock=None, backlog=100, ssl=None): if isinstance(ssl, bool): raise TypeError('ssl argument must be an SSLContext or None') diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index de41e645163..95b12a11a62 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -15,7 +15,6 @@ from . import selector_events from . import tasks from . import windows_utils -from .coroutines import coroutine from .log import logger @@ -305,17 +304,15 @@ def __init__(self, proactor=None): proactor = IocpProactor() super().__init__(proactor) - @coroutine - def create_pipe_connection(self, protocol_factory, address): + async def create_pipe_connection(self, protocol_factory, address): f = self._proactor.connect_pipe(address) - pipe = yield from f + pipe = await f protocol = protocol_factory() trans = self._make_duplex_pipe_transport(pipe, protocol, extra={'addr': address}) return trans, protocol - @coroutine - def start_serving_pipe(self, protocol_factory, address): + async def start_serving_pipe(self, protocol_factory, address): server = PipeServer(address) def loop_accept_pipe(f=None): @@ -361,28 +358,20 @@ def loop_accept_pipe(f=None): self.call_soon(loop_accept_pipe) return [server] - @coroutine - def _make_subprocess_transport(self, protocol, args, shell, - stdin, stdout, stderr, bufsize, - extra=None, **kwargs): + async def _make_subprocess_transport(self, protocol, args, shell, + stdin, stdout, stderr, bufsize, + extra=None, **kwargs): waiter = self.create_future() transp = _WindowsSubprocessTransport(self, protocol, args, shell, stdin, stdout, stderr, bufsize, waiter=waiter, extra=extra, **kwargs) try: - yield from waiter - except Exception as exc: - # Workaround CPython bug #23353: using yield/yield-from in an - # except block of a generator doesn't clear properly sys.exc_info() - err = exc - else: - err = None - - if err is not None: + await waiter + except Exception: transp.close() - yield from transp._wait() - raise err + await transp._wait() + raise return transp @@ -498,11 +487,10 @@ def finish_accept(trans, key, ov): conn.settimeout(listener.gettimeout()) return conn, conn.getpeername() - @coroutine - def accept_coro(future, conn): + async def accept_coro(future, conn): # Coroutine closing the accept socket if the future is cancelled try: - yield from future + await future except futures.CancelledError: conn.close() raise @@ -552,8 +540,7 @@ def finish_accept_pipe(trans, key, ov): return self._register(ov, pipe, finish_accept_pipe) - @coroutine - def connect_pipe(self, address): + async def connect_pipe(self, address): delay = CONNECT_PIPE_INIT_DELAY while True: # Unfortunately there is no way to do an overlapped connect to a pipe. @@ -568,7 +555,7 @@ def connect_pipe(self, address): # ConnectPipe() failed with ERROR_PIPE_BUSY: retry later delay = min(delay * 2, CONNECT_PIPE_MAX_DELAY) - yield from tasks.sleep(delay, loop=self._loop) + await tasks.sleep(delay, loop=self._loop) return windows_utils.PipeHandle(handle) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 98f2aef5627..6561a9df779 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1316,7 +1316,8 @@ def mock_getaddrinfo(*args, **kwds): self.loop.getaddrinfo.side_effect = mock_getaddrinfo self.loop.sock_connect = mock.Mock() - self.loop.sock_connect.return_value = () + self.loop.sock_connect.return_value = self.loop.create_future() + self.loop.sock_connect.return_value.set_result(None) self.loop._make_ssl_transport = mock.Mock() class _SelectorTransportMock: @@ -1416,7 +1417,8 @@ def test_create_server_no_host_port_sock(self): def test_create_server_no_getaddrinfo(self): getaddrinfo = self.loop.getaddrinfo = mock.Mock() - getaddrinfo.return_value = [] + getaddrinfo.return_value = self.loop.create_future() + getaddrinfo.return_value.set_result(None) f = self.loop.create_server(MyProto, 'python.org', 0) self.assertRaises(OSError, self.loop.run_until_complete, f) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index a6941aa4a60..2e8f46dd41e 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -285,10 +285,10 @@ def test_run_until_complete(self): self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0) def test_run_until_complete_stopped(self): - @asyncio.coroutine - def cb(): + + async def cb(): self.loop.stop() - yield from asyncio.sleep(0.1, loop=self.loop) + await asyncio.sleep(0.1, loop=self.loop) task = cb() self.assertRaises(RuntimeError, self.loop.run_until_complete, task) @@ -1424,9 +1424,8 @@ def test_read_pipe(self): rpipe, wpipe = os.pipe() pipeobj = io.open(rpipe, 'rb', 1024) - @asyncio.coroutine - def connect(): - t, p = yield from self.loop.connect_read_pipe( + async def connect(): + t, p = await self.loop.connect_read_pipe( lambda: proto, pipeobj) self.assertIs(p, proto) self.assertIs(t, proto.transport) @@ -1463,11 +1462,10 @@ def test_unclosed_pipe_transport(self): rpipeobj = io.open(rpipe, 'rb', 1024) wpipeobj = io.open(wpipe, 'w', 1024) - @asyncio.coroutine - def connect(): - read_transport, _ = yield from loop.connect_read_pipe( + async def connect(): + read_transport, _ = await loop.connect_read_pipe( lambda: read_proto, rpipeobj) - write_transport, _ = yield from loop.connect_write_pipe( + write_transport, _ = await loop.connect_write_pipe( lambda: write_proto, wpipeobj) return read_transport, write_transport @@ -1499,10 +1497,9 @@ def test_read_pty_output(self): master, slave = os.openpty() master_read_obj = io.open(master, 'rb', 0) - @asyncio.coroutine - def connect(): - t, p = yield from self.loop.connect_read_pipe(lambda: proto, - master_read_obj) + async def connect(): + t, p = await self.loop.connect_read_pipe(lambda: proto, + master_read_obj) self.assertIs(p, proto) self.assertIs(t, proto.transport) self.assertEqual(['INITIAL', 'CONNECTED'], proto.state) @@ -1713,11 +1710,10 @@ def test_prompt_cancellation(self): if ov is not None: self.assertTrue(ov.pending) - @asyncio.coroutine - def main(): + async def main(): try: self.loop.call_soon(f.cancel) - yield from f + await f except asyncio.CancelledError: res = 'cancelled' else: @@ -1750,14 +1746,13 @@ def _run_once(): self.loop._run_once_counter = 0 self.loop._run_once = _run_once - @asyncio.coroutine - def wait(): + async def wait(): loop = self.loop - yield from asyncio.sleep(1e-2, loop=loop) - yield from asyncio.sleep(1e-4, loop=loop) - yield from asyncio.sleep(1e-6, loop=loop) - yield from asyncio.sleep(1e-8, loop=loop) - yield from asyncio.sleep(1e-10, loop=loop) + await asyncio.sleep(1e-2, loop=loop) + await asyncio.sleep(1e-4, loop=loop) + await asyncio.sleep(1e-6, loop=loop) + await asyncio.sleep(1e-8, loop=loop) + await asyncio.sleep(1e-10, loop=loop) self.loop.run_until_complete(wait()) # The ideal number of call is 12, but on some platforms, the selector @@ -2076,9 +2071,9 @@ def test_subprocess_wait_no_same_group(self): self.assertEqual(7, proto.returncode) def test_subprocess_exec_invalid_args(self): - @asyncio.coroutine - def connect(**kwds): - yield from self.loop.subprocess_exec( + + async def connect(**kwds): + await self.loop.subprocess_exec( asyncio.SubprocessProtocol, 'pwd', **kwds) @@ -2090,11 +2085,11 @@ def connect(**kwds): self.loop.run_until_complete(connect(shell=True)) def test_subprocess_shell_invalid_args(self): - @asyncio.coroutine - def connect(cmd=None, **kwds): + + async def connect(cmd=None, **kwds): if not cmd: cmd = 'pwd' - yield from self.loop.subprocess_shell( + await self.loop.subprocess_shell( asyncio.SubprocessProtocol, cmd, **kwds) @@ -2548,20 +2543,8 @@ def test_not_implemented(self): NotImplementedError, loop.time) self.assertRaises( NotImplementedError, loop.call_soon_threadsafe, None) - self.assertRaises( - NotImplementedError, loop.run_in_executor, f, f) self.assertRaises( NotImplementedError, loop.set_default_executor, f) - self.assertRaises( - NotImplementedError, loop.getaddrinfo, 'localhost', 8080) - self.assertRaises( - NotImplementedError, loop.getnameinfo, ('localhost', 8080)) - self.assertRaises( - NotImplementedError, loop.create_connection, f) - self.assertRaises( - NotImplementedError, loop.create_server, f) - self.assertRaises( - NotImplementedError, loop.create_datagram_endpoint, f) self.assertRaises( NotImplementedError, loop.add_reader, 1, f) self.assertRaises( @@ -2570,33 +2553,12 @@ def test_not_implemented(self): NotImplementedError, loop.add_writer, 1, f) self.assertRaises( NotImplementedError, loop.remove_writer, 1) - self.assertRaises( - NotImplementedError, loop.sock_recv, f, 10) - self.assertRaises( - NotImplementedError, loop.sock_recv_into, f, 10) - self.assertRaises( - NotImplementedError, loop.sock_sendall, f, 10) - self.assertRaises( - NotImplementedError, loop.sock_connect, f, f) - self.assertRaises( - NotImplementedError, loop.sock_accept, f) self.assertRaises( NotImplementedError, loop.add_signal_handler, 1, f) self.assertRaises( NotImplementedError, loop.remove_signal_handler, 1) self.assertRaises( NotImplementedError, loop.remove_signal_handler, 1) - self.assertRaises( - NotImplementedError, loop.connect_read_pipe, f, - mock.sentinel.pipe) - self.assertRaises( - NotImplementedError, loop.connect_write_pipe, f, - mock.sentinel.pipe) - self.assertRaises( - NotImplementedError, loop.subprocess_shell, f, - mock.sentinel) - self.assertRaises( - NotImplementedError, loop.subprocess_exec, f) self.assertRaises( NotImplementedError, loop.set_exception_handler, f) self.assertRaises( @@ -2608,6 +2570,47 @@ def test_not_implemented(self): self.assertRaises( NotImplementedError, loop.set_debug, f) + def test_not_implemented_async(self): + + async def inner(): + f = mock.Mock() + loop = asyncio.AbstractEventLoop() + + with self.assertRaises(NotImplementedError): + await loop.run_in_executor(f, f) + with self.assertRaises(NotImplementedError): + await loop.getaddrinfo('localhost', 8080) + with self.assertRaises(NotImplementedError): + await loop.getnameinfo(('localhost', 8080)) + with self.assertRaises(NotImplementedError): + await loop.create_connection(f) + with self.assertRaises(NotImplementedError): + await loop.create_server(f) + with self.assertRaises(NotImplementedError): + await loop.create_datagram_endpoint(f) + with self.assertRaises(NotImplementedError): + await loop.sock_recv(f, 10) + with self.assertRaises(NotImplementedError): + await loop.sock_recv_into(f, 10) + with self.assertRaises(NotImplementedError): + await loop.sock_sendall(f, 10) + with self.assertRaises(NotImplementedError): + await loop.sock_connect(f, f) + with self.assertRaises(NotImplementedError): + await loop.sock_accept(f) + with self.assertRaises(NotImplementedError): + await loop.connect_read_pipe(f, mock.sentinel.pipe) + with self.assertRaises(NotImplementedError): + await loop.connect_write_pipe(f, mock.sentinel.pipe) + with self.assertRaises(NotImplementedError): + await loop.subprocess_shell(f, mock.sentinel) + with self.assertRaises(NotImplementedError): + await loop.subprocess_exec(f) + + loop = asyncio.new_event_loop() + loop.run_until_complete(inner()) + loop.close() + class ProtocolsAbsTests(unittest.TestCase): diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index c85e8b1a32f..c1f8d6e3673 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -69,21 +69,18 @@ def test_acquire(self): self.assertTrue(self.loop.run_until_complete(lock.acquire())) - @asyncio.coroutine - def c1(result): - if (yield from lock.acquire()): + async def c1(result): + if await lock.acquire(): result.append(1) return True - @asyncio.coroutine - def c2(result): - if (yield from lock.acquire()): + async def c2(result): + if await lock.acquire(): result.append(2) return True - @asyncio.coroutine - def c3(result): - if (yield from lock.acquire()): + async def c3(result): + if await lock.acquire(): result.append(3) return True @@ -145,12 +142,11 @@ def test_cancel_race(self): # Setup: A has the lock, b and c are waiting. lock = asyncio.Lock(loop=self.loop) - @asyncio.coroutine - def lockit(name, blocker): - yield from lock.acquire() + async def lockit(name, blocker): + await lock.acquire() try: if blocker is not None: - yield from blocker + await blocker finally: lock.release() @@ -294,19 +290,16 @@ def test_wait(self): result = [] - @asyncio.coroutine - def c1(result): - if (yield from ev.wait()): + async def c1(result): + if await ev.wait(): result.append(1) - @asyncio.coroutine - def c2(result): - if (yield from ev.wait()): + async def c2(result): + if await ev.wait(): result.append(2) - @asyncio.coroutine - def c3(result): - if (yield from ev.wait()): + async def c3(result): + if await ev.wait(): result.append(3) t1 = asyncio.Task(c1(result), loop=self.loop) @@ -359,9 +352,8 @@ def test_clear_with_waiters(self): ev = asyncio.Event(loop=self.loop) result = [] - @asyncio.coroutine - def c1(result): - if (yield from ev.wait()): + async def c1(result): + if await ev.wait(): result.append(1) return True @@ -408,24 +400,21 @@ def test_wait(self): cond = asyncio.Condition(loop=self.loop) result = [] - @asyncio.coroutine - def c1(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c1(result): + await cond.acquire() + if await cond.wait(): result.append(1) return True - @asyncio.coroutine - def c2(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c2(result): + await cond.acquire() + if await cond.wait(): result.append(2) return True - @asyncio.coroutine - def c3(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c3(result): + await cond.acquire() + if await cond.wait(): result.append(3) return True @@ -522,10 +511,9 @@ def predicate(): result = [] - @asyncio.coroutine - def c1(result): - yield from cond.acquire() - if (yield from cond.wait_for(predicate)): + async def c1(result): + await cond.acquire() + if await cond.wait_for(predicate): result.append(1) cond.release() return True @@ -567,26 +555,23 @@ def test_notify(self): cond = asyncio.Condition(loop=self.loop) result = [] - @asyncio.coroutine - def c1(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c1(result): + await cond.acquire() + if await cond.wait(): result.append(1) cond.release() return True - @asyncio.coroutine - def c2(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c2(result): + await cond.acquire() + if await cond.wait(): result.append(2) cond.release() return True - @asyncio.coroutine - def c3(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c3(result): + await cond.acquire() + if await cond.wait(): result.append(3) cond.release() return True @@ -623,18 +608,16 @@ def test_notify_all(self): result = [] - @asyncio.coroutine - def c1(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c1(result): + await cond.acquire() + if await cond.wait(): result.append(1) cond.release() return True - @asyncio.coroutine - def c2(result): - yield from cond.acquire() - if (yield from cond.wait()): + async def c2(result): + await cond.acquire() + if await cond.wait(): result.append(2) cond.release() return True @@ -791,27 +774,23 @@ def test_acquire(self): self.assertTrue(self.loop.run_until_complete(sem.acquire())) self.assertFalse(sem.locked()) - @asyncio.coroutine - def c1(result): - yield from sem.acquire() + async def c1(result): + await sem.acquire() result.append(1) return True - @asyncio.coroutine - def c2(result): - yield from sem.acquire() + async def c2(result): + await sem.acquire() result.append(2) return True - @asyncio.coroutine - def c3(result): - yield from sem.acquire() + async def c3(result): + await sem.acquire() result.append(3) return True - @asyncio.coroutine - def c4(result): - yield from sem.acquire() + async def c4(result): + await sem.acquire() result.append(4) return True diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py index 2137cde6f48..3b66d616f8e 100644 --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -36,27 +36,25 @@ def gen(): id_is_present = hex(id(q)) in fn(q) self.assertEqual(expect_id, id_is_present) - @asyncio.coroutine - def add_getter(): + async def add_getter(): q = asyncio.Queue(loop=loop) # Start a task that waits to get. asyncio.Task(q.get(), loop=loop) # Let it start waiting. - yield from asyncio.sleep(0.1, loop=loop) + await asyncio.sleep(0.1, loop=loop) self.assertTrue('_getters[1]' in fn(q)) # resume q.get coroutine to finish generator q.put_nowait(0) loop.run_until_complete(add_getter()) - @asyncio.coroutine - def add_putter(): + async def add_putter(): q = asyncio.Queue(maxsize=1, loop=loop) q.put_nowait(1) # Start a task that waits to put. asyncio.Task(q.put(2), loop=loop) # Let it start waiting. - yield from asyncio.sleep(0.1, loop=loop) + await asyncio.sleep(0.1, loop=loop) self.assertTrue('_putters[1]' in fn(q)) # resume q.put coroutine to finish generator q.get_nowait() @@ -125,24 +123,22 @@ def gen(): self.assertEqual(2, q.maxsize) have_been_put = [] - @asyncio.coroutine - def putter(): + async def putter(): for i in range(3): - yield from q.put(i) + await q.put(i) have_been_put.append(i) return True - @asyncio.coroutine - def test(): + async def test(): t = asyncio.Task(putter(), loop=loop) - yield from asyncio.sleep(0.01, loop=loop) + await asyncio.sleep(0.01, loop=loop) # The putter is blocked after putting two items. self.assertEqual([0, 1], have_been_put) self.assertEqual(0, q.get_nowait()) # Let the putter resume and put last item. - yield from asyncio.sleep(0.01, loop=loop) + await asyncio.sleep(0.01, loop=loop) self.assertEqual([0, 1, 2], have_been_put) self.assertEqual(1, q.get_nowait()) self.assertEqual(2, q.get_nowait()) @@ -160,9 +156,8 @@ def test_blocking_get(self): q = asyncio.Queue(loop=self.loop) q.put_nowait(1) - @asyncio.coroutine - def queue_get(): - return (yield from q.get()) + async def queue_get(): + return await q.get() res = self.loop.run_until_complete(queue_get()) self.assertEqual(1, res) @@ -192,21 +187,19 @@ def gen(): started = asyncio.Event(loop=loop) finished = False - @asyncio.coroutine - def queue_get(): + async def queue_get(): nonlocal finished started.set() - res = yield from q.get() + res = await q.get() finished = True return res - @asyncio.coroutine - def queue_put(): + async def queue_put(): loop.call_later(0.01, q.put_nowait, 1) queue_get_task = asyncio.Task(queue_get(), loop=loop) - yield from started.wait() + await started.wait() self.assertFalse(finished) - res = yield from queue_get_task + res = await queue_get_task self.assertTrue(finished) return res @@ -236,16 +229,14 @@ def gen(): q = asyncio.Queue(loop=loop) - @asyncio.coroutine - def queue_get(): - return (yield from asyncio.wait_for(q.get(), 0.051, loop=loop)) + async def queue_get(): + return await asyncio.wait_for(q.get(), 0.051, loop=loop) - @asyncio.coroutine - def test(): + async def test(): get_task = asyncio.Task(queue_get(), loop=loop) - yield from asyncio.sleep(0.01, loop=loop) # let the task start + await asyncio.sleep(0.01, loop=loop) # let the task start q.put_nowait(1) - return (yield from get_task) + return await get_task self.assertEqual(1, loop.run_until_complete(test())) self.assertAlmostEqual(0.06, loop.time()) @@ -275,15 +266,13 @@ def test_get_with_waiting_putters(self): def test_why_are_getters_waiting(self): # From issue #268. - @asyncio.coroutine - def consumer(queue, num_expected): + async def consumer(queue, num_expected): for _ in range(num_expected): - yield from queue.get() + await queue.get() - @asyncio.coroutine - def producer(queue, num_items): + async def producer(queue, num_items): for i in range(num_items): - yield from queue.put(i) + await queue.put(i) queue_size = 1 producer_num_items = 5 @@ -301,10 +290,10 @@ def a_generator(): yield 0.2 self.loop = self.new_test_loop(a_generator) - @asyncio.coroutine - def consumer(queue): + + async def consumer(queue): try: - item = yield from asyncio.wait_for(queue.get(), 0.1, loop=self.loop) + item = await asyncio.wait_for(queue.get(), 0.1, loop=self.loop) except asyncio.TimeoutError: pass @@ -318,10 +307,9 @@ class QueuePutTests(_QueueTestBase): def test_blocking_put(self): q = asyncio.Queue(loop=self.loop) - @asyncio.coroutine - def queue_put(): + async def queue_put(): # No maxsize, won't block. - yield from q.put(1) + await q.put(1) self.loop.run_until_complete(queue_put()) @@ -338,21 +326,19 @@ def gen(): started = asyncio.Event(loop=loop) finished = False - @asyncio.coroutine - def queue_put(): + async def queue_put(): nonlocal finished started.set() - yield from q.put(1) - yield from q.put(2) + await q.put(1) + await q.put(2) finished = True - @asyncio.coroutine - def queue_get(): + async def queue_get(): loop.call_later(0.01, q.get_nowait) queue_put_task = asyncio.Task(queue_put(), loop=loop) - yield from started.wait() + await started.wait() self.assertFalse(finished) - yield from queue_put_task + await queue_put_task self.assertTrue(finished) loop.run_until_complete(queue_get()) @@ -464,24 +450,22 @@ def test_float_maxsize(self): self.assertRaises(asyncio.QueueFull, q.put_nowait, 3) q = asyncio.Queue(maxsize=1.3, loop=self.loop) - @asyncio.coroutine - def queue_put(): - yield from q.put(1) - yield from q.put(2) + + async def queue_put(): + await q.put(1) + await q.put(2) self.assertTrue(q.full()) self.loop.run_until_complete(queue_put()) def test_put_cancelled(self): q = asyncio.Queue(loop=self.loop) - @asyncio.coroutine - def queue_put(): - yield from q.put(1) + async def queue_put(): + await q.put(1) return True - @asyncio.coroutine - def test(): - return (yield from q.get()) + async def test(): + return await q.get() t = asyncio.Task(queue_put(), loop=self.loop) self.assertEqual(1, self.loop.run_until_complete(test())) @@ -520,13 +504,11 @@ def test_why_are_putters_waiting(self): queue = asyncio.Queue(2, loop=self.loop) - @asyncio.coroutine - def putter(item): - yield from queue.put(item) + async def putter(item): + await queue.put(item) - @asyncio.coroutine - def getter(): - yield + async def getter(): + await asyncio.sleep(0, loop=self.loop) num = queue.qsize() for _ in range(num): item = queue.get_nowait() @@ -580,21 +562,19 @@ def test_task_done(self): # Join the queue and assert all items have been processed. running = True - @asyncio.coroutine - def worker(): + async def worker(): nonlocal accumulator while running: - item = yield from q.get() + item = await q.get() accumulator += item q.task_done() - @asyncio.coroutine - def test(): + async def test(): tasks = [asyncio.Task(worker(), loop=self.loop) for index in range(2)] - yield from q.join() + await q.join() return tasks tasks = self.loop.run_until_complete(test()) @@ -612,10 +592,9 @@ def test_join_empty_queue(self): # Test that a queue join()s successfully, and before anything else # (done twice for insurance). - @asyncio.coroutine - def join(): - yield from q.join() - yield from q.join() + async def join(): + await q.join() + await q.join() self.loop.run_until_complete(join()) diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index a1e5bd7fab6..2f4e6d23bf9 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -571,11 +571,10 @@ def __init__(self, loop): self.server = None self.loop = loop - @asyncio.coroutine - def handle_client(self, client_reader, client_writer): - data = yield from client_reader.readline() + async def handle_client(self, client_reader, client_writer): + data = await client_reader.readline() client_writer.write(data) - yield from client_writer.drain() + await client_writer.drain() client_writer.close() def start(self): @@ -608,14 +607,13 @@ def stop(self): self.loop.run_until_complete(self.server.wait_closed()) self.server = None - @asyncio.coroutine - def client(addr): - reader, writer = yield from asyncio.open_connection( + async def client(addr): + reader, writer = await asyncio.open_connection( *addr, loop=self.loop) # send a line writer.write(b"hello world!\n") # read it back - msgback = yield from reader.readline() + msgback = await reader.readline() writer.close() return msgback @@ -645,11 +643,10 @@ def __init__(self, loop, path): self.loop = loop self.path = path - @asyncio.coroutine - def handle_client(self, client_reader, client_writer): - data = yield from client_reader.readline() + async def handle_client(self, client_reader, client_writer): + data = await client_reader.readline() client_writer.write(data) - yield from client_writer.drain() + await client_writer.drain() client_writer.close() def start(self): @@ -674,14 +671,13 @@ def stop(self): self.loop.run_until_complete(self.server.wait_closed()) self.server = None - @asyncio.coroutine - def client(path): - reader, writer = yield from asyncio.open_unix_connection( + async def client(path): + reader, writer = await asyncio.open_unix_connection( path, loop=self.loop) # send a line writer.write(b"hello world!\n") # read it back - msgback = yield from reader.readline() + msgback = await reader.readline() writer.close() return msgback @@ -782,14 +778,13 @@ def server(): clt, _ = sock.accept() clt.close() - @asyncio.coroutine - def client(host, port): - reader, writer = yield from asyncio.open_connection( + async def client(host, port): + reader, writer = await asyncio.open_connection( host, port, loop=self.loop) while True: writer.write(b"foo\n") - yield from writer.drain() + await writer.drain() # Start the server thread and wait for it to be listening. thread = threading.Thread(target=server) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index e8822c36698..ad4bb149559 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -81,9 +81,8 @@ class SubprocessMixin: def test_stdin_stdout(self): args = PROGRAM_CAT - @asyncio.coroutine - def run(data): - proc = yield from asyncio.create_subprocess_exec( + async def run(data): + proc = await asyncio.create_subprocess_exec( *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, @@ -91,12 +90,12 @@ def run(data): # feed data proc.stdin.write(data) - yield from proc.stdin.drain() + await proc.stdin.drain() proc.stdin.close() # get output and exitcode - data = yield from proc.stdout.read() - exitcode = yield from proc.wait() + data = await proc.stdout.read() + exitcode = await proc.wait() return (exitcode, data) task = run(b'some data') @@ -108,14 +107,13 @@ def run(data): def test_communicate(self): args = PROGRAM_CAT - @asyncio.coroutine - def run(data): - proc = yield from asyncio.create_subprocess_exec( + async def run(data): + proc = await asyncio.create_subprocess_exec( *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, loop=self.loop) - stdout, stderr = yield from proc.communicate(data) + stdout, stderr = await proc.communicate(data) return proc.returncode, stdout task = run(b'some data') @@ -178,14 +176,13 @@ def test_send_signal(self): loop=self.loop) proc = self.loop.run_until_complete(create) - @asyncio.coroutine - def send_signal(proc): + async def send_signal(proc): # basic synchronization to wait until the program is sleeping - line = yield from proc.stdout.readline() + line = await proc.stdout.readline() self.assertEqual(line, b'sleeping\n') proc.send_signal(signal.SIGHUP) - returncode = (yield from proc.wait()) + returncode = await proc.wait() return returncode returncode = self.loop.run_until_complete(send_signal(proc)) @@ -208,10 +205,9 @@ def prepare_broken_pipe_test(self): def test_stdin_broken_pipe(self): proc, large_data = self.prepare_broken_pipe_test() - @asyncio.coroutine - def write_stdin(proc, data): + async def write_stdin(proc, data): proc.stdin.write(data) - yield from proc.stdin.drain() + await proc.stdin.drain() coro = write_stdin(proc, large_data) # drain() must raise BrokenPipeError or ConnectionResetError @@ -232,8 +228,7 @@ def test_pause_reading(self): limit = 10 size = (limit * 2 + 1) - @asyncio.coroutine - def test_pause_reading(): + async def test_pause_reading(): code = '\n'.join(( 'import sys', 'sys.stdout.write("x" * %s)' % size, @@ -242,16 +237,15 @@ def test_pause_reading(): connect_read_pipe = self.loop.connect_read_pipe - @asyncio.coroutine - def connect_read_pipe_mock(*args, **kw): - transport, protocol = yield from connect_read_pipe(*args, **kw) + async def connect_read_pipe_mock(*args, **kw): + transport, protocol = await connect_read_pipe(*args, **kw) transport.pause_reading = mock.Mock() transport.resume_reading = mock.Mock() return (transport, protocol) self.loop.connect_read_pipe = connect_read_pipe_mock - proc = yield from asyncio.create_subprocess_exec( + proc = await asyncio.create_subprocess_exec( sys.executable, '-c', code, stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE, @@ -259,7 +253,7 @@ def connect_read_pipe_mock(*args, **kw): loop=self.loop) stdout_transport = proc._transport.get_pipe_transport(1) - stdout, stderr = yield from proc.communicate() + stdout, stderr = await proc.communicate() # The child process produced more than limit bytes of output, # the stream reader transport should pause the protocol to not @@ -277,18 +271,17 @@ def connect_read_pipe_mock(*args, **kw): def test_stdin_not_inheritable(self): # asyncio issue #209: stdin must not be inheritable, otherwise # the Process.communicate() hangs - @asyncio.coroutine - def len_message(message): + async def len_message(message): code = 'import sys; data = sys.stdin.read(); print(len(data))' - proc = yield from asyncio.create_subprocess_exec( + proc = await asyncio.create_subprocess_exec( sys.executable, '-c', code, stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, close_fds=False, loop=self.loop) - stdout, stderr = yield from proc.communicate(message) - exitcode = yield from proc.wait() + stdout, stderr = await proc.communicate(message) + exitcode = await proc.wait() return (stdout, exitcode) output, exitcode = self.loop.run_until_complete(len_message(b'abc')) @@ -296,18 +289,18 @@ def len_message(message): self.assertEqual(exitcode, 0) def test_empty_input(self): - @asyncio.coroutine - def empty_input(): + + async def empty_input(): code = 'import sys; data = sys.stdin.read(); print(len(data))' - proc = yield from asyncio.create_subprocess_exec( + proc = await asyncio.create_subprocess_exec( sys.executable, '-c', code, stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, close_fds=False, loop=self.loop) - stdout, stderr = yield from proc.communicate(b'') - exitcode = yield from proc.wait() + stdout, stderr = await proc.communicate(b'') + exitcode = await proc.wait() return (stdout, exitcode) output, exitcode = self.loop.run_until_complete(empty_input()) @@ -317,9 +310,8 @@ def empty_input(): def test_cancel_process_wait(self): # Issue #23140: cancel Process.wait() - @asyncio.coroutine - def cancel_wait(): - proc = yield from asyncio.create_subprocess_exec( + async def cancel_wait(): + proc = await asyncio.create_subprocess_exec( *PROGRAM_BLOCKED, loop=self.loop) @@ -327,7 +319,7 @@ def cancel_wait(): task = self.loop.create_task(proc.wait()) self.loop.call_soon(task.cancel) try: - yield from task + await task except asyncio.CancelledError: pass @@ -336,20 +328,20 @@ def cancel_wait(): # Kill the process and wait until it is done proc.kill() - yield from proc.wait() + await proc.wait() self.loop.run_until_complete(cancel_wait()) def test_cancel_make_subprocess_transport_exec(self): - @asyncio.coroutine - def cancel_make_transport(): + + async def cancel_make_transport(): coro = asyncio.create_subprocess_exec(*PROGRAM_BLOCKED, loop=self.loop) task = self.loop.create_task(coro) self.loop.call_soon(task.cancel) try: - yield from task + await task except asyncio.CancelledError: pass @@ -359,15 +351,15 @@ def cancel_make_transport(): self.loop.run_until_complete(cancel_make_transport()) def test_cancel_post_init(self): - @asyncio.coroutine - def cancel_make_transport(): + + async def cancel_make_transport(): coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *PROGRAM_BLOCKED) task = self.loop.create_task(coro) self.loop.call_soon(task.cancel) try: - yield from task + await task except asyncio.CancelledError: pass @@ -378,11 +370,11 @@ def cancel_make_transport(): test_utils.run_briefly(self.loop) def test_close_kill_running(self): - @asyncio.coroutine - def kill_running(): + + async def kill_running(): create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *PROGRAM_BLOCKED) - transport, protocol = yield from create + transport, protocol = await create kill_called = False def kill(): @@ -395,7 +387,7 @@ def kill(): proc.kill = kill returncode = transport.get_returncode() transport.close() - yield from transport._wait() + await transport._wait() return (returncode, kill_called) # Ignore "Close running child process: kill ..." log @@ -408,11 +400,11 @@ def kill(): test_utils.run_briefly(self.loop) def test_close_dont_kill_finished(self): - @asyncio.coroutine - def kill_running(): + + async def kill_running(): create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *PROGRAM_BLOCKED) - transport, protocol = yield from create + transport, protocol = await create proc = transport.get_extra_info('subprocess') # kill the process (but asyncio is not notified immediately) @@ -444,8 +436,8 @@ def kill_running(): # Unlike SafeChildWatcher, FastChildWatcher does not pop the # callbacks if waitpid() is called elsewhere. Let's clear them # manually to avoid a warning when the watcher is detached. - if sys.platform != 'win32' and \ - isinstance(self, SubprocessFastWatcherTests): + if (sys.platform != 'win32' and + isinstance(self, SubprocessFastWatcherTests)): asyncio.get_child_watcher()._callbacks.clear() def test_popen_error(self): @@ -467,8 +459,8 @@ def test_popen_error(self): self.assertEqual(warns, []) def test_read_stdout_after_process_exit(self): - @asyncio.coroutine - def execute(): + + async def execute(): code = '\n'.join(['import sys', 'for _ in range(64):', ' sys.stdout.write("x" * 4096)', @@ -480,11 +472,11 @@ def execute(): stdout=asyncio.subprocess.PIPE, loop=self.loop) - process = yield from fut + process = await fut while True: - data = yield from process.stdout.read(65536) + data = await process.stdout.read(65536) if data: - yield from asyncio.sleep(0.3, loop=self.loop) + await asyncio.sleep(0.3, loop=self.loop) else: break diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index f66f7f1e170..cdc882a9bee 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -31,10 +31,6 @@ from asyncio.test_support import assert_python_ok -PY34 = (sys.version_info >= (3, 4)) -PY35 = (sys.version_info >= (3, 5)) - - @asyncio.coroutine def coroutine_function(): pass @@ -110,9 +106,8 @@ def test_other_loop_future(self): other_loop = asyncio.new_event_loop() fut = self.new_future(other_loop) - @asyncio.coroutine - def run(fut): - yield from fut + async def run(fut): + await fut try: with self.assertRaisesRegex(RuntimeError, @@ -122,9 +117,9 @@ def run(fut): other_loop.close() def test_task_awaits_on_itself(self): - @asyncio.coroutine - def test(): - yield from task + + async def test(): + await task task = asyncio.ensure_future(test(), loop=self.loop) @@ -209,7 +204,6 @@ def notmuch(): t = asyncio.ensure_future(t_orig, loop=self.loop) self.assertIs(t, t_orig) - @unittest.skipUnless(PY35, 'need python 3.5 or later') def test_ensure_future_awaitable(self): class Aw: def __init__(self, coro): @@ -234,12 +228,10 @@ def test_ensure_future_neither(self): def test_get_stack(self): T = None - @asyncio.coroutine - def foo(): - yield from bar() + async def foo(): + await bar() - @asyncio.coroutine - def bar(): + async def bar(): # test get_stack() f = T.get_stack(limit=1) try: @@ -254,11 +246,10 @@ def bar(): tb = file.read() self.assertRegex(tb, r'foo\(\) running') - @asyncio.coroutine - def runner(): + async def runner(): nonlocal T T = asyncio.ensure_future(foo(), loop=self.loop) - yield from T + await T self.loop.run_until_complete(runner()) @@ -272,9 +263,8 @@ def notmuch(): # test coroutine function self.assertEqual(notmuch.__name__, 'notmuch') - if PY35: - self.assertRegex(notmuch.__qualname__, - r'\w+.test_task_repr..notmuch') + self.assertRegex(notmuch.__qualname__, + r'\w+.test_task_repr..notmuch') self.assertEqual(notmuch.__module__, __name__) filename, lineno = test_utils.get_function_source(notmuch) @@ -282,14 +272,9 @@ def notmuch(): # test coroutine object gen = notmuch() - if coroutines._DEBUG or PY35: - coro_qualname = 'BaseTaskTests.test_task_repr..notmuch' - else: - coro_qualname = 'notmuch' + coro_qualname = 'BaseTaskTests.test_task_repr..notmuch' self.assertEqual(gen.__name__, 'notmuch') - if PY35: - self.assertEqual(gen.__qualname__, - coro_qualname) + self.assertEqual(gen.__qualname__, coro_qualname) # test pending Task t = self.new_task(self.loop, gen) @@ -332,28 +317,21 @@ def notmuch(): # test coroutine function self.assertEqual(notmuch.__name__, 'notmuch') - if PY35: - self.assertRegex(notmuch.__qualname__, - r'\w+.test_task_repr_coro_decorator' - r'\.\.notmuch') + self.assertRegex(notmuch.__qualname__, + r'\w+.test_task_repr_coro_decorator' + r'\.\.notmuch') self.assertEqual(notmuch.__module__, __name__) # test coroutine object gen = notmuch() - if coroutines._DEBUG or PY35: - # On Python >= 3.5, generators now inherit the name of the - # function, as expected, and have a qualified name (__qualname__ - # attribute). - coro_name = 'notmuch' - coro_qualname = ('BaseTaskTests.test_task_repr_coro_decorator' - '..notmuch') - else: - # On Python < 3.5, generators inherit the name of the code, not of - # the function. See: http://bugs.python.org/issue21205 - coro_name = coro_qualname = 'coro' + # On Python >= 3.5, generators now inherit the name of the + # function, as expected, and have a qualified name (__qualname__ + # attribute). + coro_name = 'notmuch' + coro_qualname = ('BaseTaskTests.test_task_repr_coro_decorator' + '..notmuch') self.assertEqual(gen.__name__, coro_name) - if PY35: - self.assertEqual(gen.__qualname__, coro_qualname) + self.assertEqual(gen.__qualname__, coro_qualname) # test repr(CoroWrapper) if coroutines._DEBUG: @@ -392,9 +370,8 @@ def notmuch(): def test_task_repr_wait_for(self): self.loop.set_debug(False) - @asyncio.coroutine - def wait_for(fut): - return (yield from fut) + async def wait_for(fut): + return await fut fut = self.new_future(self.loop) task = self.new_task(self.loop, wait_for(fut)) @@ -411,9 +388,8 @@ def test_task_repr_partial_corowrapper(self): with set_coroutine_debug(True): self.loop.set_debug(True) - @asyncio.coroutine - def func(x, y): - yield from asyncio.sleep(0) + async def func(x, y): + await asyncio.sleep(0) partial_func = asyncio.coroutine(functools.partial(func, 1)) task = self.loop.create_task(partial_func(2)) @@ -430,18 +406,16 @@ def func(x, y): self.assertRegex(coro_repr, expected) def test_task_basics(self): - @asyncio.coroutine - def outer(): - a = yield from inner1() - b = yield from inner2() + + async def outer(): + a = await inner1() + b = await inner2() return a+b - @asyncio.coroutine - def inner1(): + async def inner1(): return 42 - @asyncio.coroutine - def inner2(): + async def inner2(): return 1000 t = outer() @@ -456,9 +430,8 @@ def gen(): loop = self.new_test_loop(gen) - @asyncio.coroutine - def task(): - yield from asyncio.sleep(10.0, loop=loop) + async def task(): + await asyncio.sleep(10.0, loop=loop) return 12 t = self.new_task(loop, task()) @@ -488,9 +461,8 @@ def task(): def test_cancel_inner_future(self): f = self.new_future(self.loop) - @asyncio.coroutine - def task(): - yield from f + async def task(): + await f return 12 t = self.new_task(self.loop, task()) @@ -504,9 +476,8 @@ def task(): def test_cancel_both_task_and_inner_future(self): f = self.new_future(self.loop) - @asyncio.coroutine - def task(): - yield from f + async def task(): + await f return 12 t = self.new_task(self.loop, task()) @@ -526,11 +497,10 @@ def test_cancel_task_catching(self): fut1 = self.new_future(self.loop) fut2 = self.new_future(self.loop) - @asyncio.coroutine - def task(): - yield from fut1 + async def task(): + await fut1 try: - yield from fut2 + await fut2 except asyncio.CancelledError: return 42 @@ -551,14 +521,13 @@ def test_cancel_task_ignoring(self): fut2 = self.new_future(self.loop) fut3 = self.new_future(self.loop) - @asyncio.coroutine - def task(): - yield from fut1 + async def task(): + await fut1 try: - yield from fut2 + await fut2 except asyncio.CancelledError: pass - res = yield from fut3 + res = await fut3 return res t = self.new_task(self.loop, task()) @@ -581,12 +550,11 @@ def test_cancel_current_task(self): loop = asyncio.new_event_loop() self.set_event_loop(loop) - @asyncio.coroutine - def task(): + async def task(): t.cancel() self.assertTrue(t._must_cancel) # White-box test. # The sleep should be cancelled immediately. - yield from asyncio.sleep(100, loop=loop) + await asyncio.sleep(100, loop=loop) return 12 t = self.new_task(loop, task()) @@ -628,14 +596,11 @@ def gen(): loop = self.new_test_loop(gen) x = 0 - waiters = [] - @asyncio.coroutine - def task(): + async def task(): nonlocal x while x < 10: - waiters.append(asyncio.sleep(0.1, loop=loop)) - yield from waiters[-1] + await asyncio.sleep(0.1, loop=loop) x += 1 if x == 2: loop.stop() @@ -649,9 +614,6 @@ def task(): self.assertEqual(x, 2) self.assertAlmostEqual(0.3, loop.time()) - # close generators - for w in waiters: - w.close() t.cancel() self.assertRaises(asyncio.CancelledError, loop.run_until_complete, t) @@ -704,12 +666,11 @@ def gen(): foo_running = None - @asyncio.coroutine - def foo(): + async def foo(): nonlocal foo_running foo_running = True try: - yield from asyncio.sleep(0.2, loop=loop) + await asyncio.sleep(0.2, loop=loop) finally: foo_running = False return 'done' @@ -738,12 +699,11 @@ def gen(): foo_running = None - @asyncio.coroutine - def foo(): + async def foo(): nonlocal foo_running foo_running = True try: - yield from asyncio.sleep(0.2, loop=loop) + await asyncio.sleep(0.2, loop=loop) finally: foo_running = False return 'done' @@ -781,9 +741,8 @@ def gen(): loop = self.new_test_loop(gen) - @asyncio.coroutine - def foo(): - yield from asyncio.sleep(0.2, loop=loop) + async def foo(): + await asyncio.sleep(0.2, loop=loop) return 'done' asyncio.set_event_loop(loop) @@ -827,9 +786,8 @@ def gen(): a = self.new_task(loop, asyncio.sleep(0.1, loop=loop)) b = self.new_task(loop, asyncio.sleep(0.15, loop=loop)) - @asyncio.coroutine - def foo(): - done, pending = yield from asyncio.wait([b, a], loop=loop) + async def foo(): + done, pending = await asyncio.wait([b, a], loop=loop) self.assertEqual(done, set([a, b])) self.assertEqual(pending, set()) return 42 @@ -857,9 +815,8 @@ def gen(): a = self.new_task(loop, asyncio.sleep(0.01, loop=loop)) b = self.new_task(loop, asyncio.sleep(0.015, loop=loop)) - @asyncio.coroutine - def foo(): - done, pending = yield from asyncio.wait([b, a]) + async def foo(): + done, pending = await asyncio.wait([b, a]) self.assertEqual(done, set([a, b])) self.assertEqual(pending, set()) return 42 @@ -871,6 +828,7 @@ def foo(): self.assertEqual(res, 42) def test_wait_duplicate_coroutines(self): + @asyncio.coroutine def coro(s): return s @@ -1000,9 +958,8 @@ def gen(): # first_exception, exception during waiting a = self.new_task(loop, asyncio.sleep(10.0, loop=loop)) - @asyncio.coroutine - def exc(): - yield from asyncio.sleep(0.01, loop=loop) + async def exc(): + await asyncio.sleep(0.01, loop=loop) raise ZeroDivisionError('err') b = self.new_task(loop, exc()) @@ -1038,9 +995,8 @@ def sleeper(): b = self.new_task(loop, sleeper()) - @asyncio.coroutine - def foo(): - done, pending = yield from asyncio.wait([b, a], loop=loop) + async def foo(): + done, pending = await asyncio.wait([b, a], loop=loop) self.assertEqual(len(done), 2) self.assertEqual(pending, set()) errors = set(f for f in done if f.exception() is not None) @@ -1068,9 +1024,8 @@ def gen(): a = self.new_task(loop, asyncio.sleep(0.1, loop=loop)) b = self.new_task(loop, asyncio.sleep(0.15, loop=loop)) - @asyncio.coroutine - def foo(): - done, pending = yield from asyncio.wait([b, a], timeout=0.11, + async def foo(): + done, pending = await asyncio.wait([b, a], timeout=0.11, loop=loop) self.assertEqual(done, set([a])) self.assertEqual(pending, set([b])) @@ -1164,17 +1119,16 @@ def gen(): loop = self.new_test_loop(gen) - a = asyncio.sleep(0.1, 'a', loop=loop) - b = asyncio.sleep(0.15, 'b', loop=loop) + a = loop.create_task(asyncio.sleep(0.1, 'a', loop=loop)) + b = loop.create_task(asyncio.sleep(0.15, 'b', loop=loop)) - @asyncio.coroutine - def foo(): + async def foo(): values = [] for f in asyncio.as_completed([a, b], timeout=0.12, loop=loop): if values: loop.advance_time(0.02) try: - v = yield from f + v = await f values.append((1, v)) except asyncio.TimeoutError as exc: values.append((2, exc)) @@ -1202,10 +1156,9 @@ def gen(): a = asyncio.sleep(0.01, 'a', loop=loop) - @asyncio.coroutine - def foo(): + async def foo(): for f in asyncio.as_completed([a], timeout=1, loop=loop): - v = yield from f + v = await f self.assertEqual(v, 'a') loop.run_until_complete(self.new_task(loop, foo())) @@ -1578,18 +1531,16 @@ def test_current_task_with_interleaving_tasks(self): fut1 = self.new_future(self.loop) fut2 = self.new_future(self.loop) - @asyncio.coroutine - def coro1(loop): + async def coro1(loop): self.assertTrue(Task.current_task(loop=loop) is task1) - yield from fut1 + await fut1 self.assertTrue(Task.current_task(loop=loop) is task1) fut2.set_result(True) - @asyncio.coroutine - def coro2(loop): + async def coro2(loop): self.assertTrue(Task.current_task(loop=loop) is task2) fut1.set_result(True) - yield from fut2 + await fut2 self.assertTrue(Task.current_task(loop=loop) is task2) task1 = self.new_task(self.loop, coro1(self.loop)) @@ -1607,22 +1558,20 @@ def test_yield_future_passes_cancel(self): proof = 0 waiter = self.new_future(self.loop) - @asyncio.coroutine - def inner(): + async def inner(): nonlocal proof try: - yield from waiter + await waiter except asyncio.CancelledError: proof += 1 raise else: self.fail('got past sleep() in inner()') - @asyncio.coroutine - def outer(): + async def outer(): nonlocal proof try: - yield from inner() + await inner() except asyncio.CancelledError: proof += 100 # Expect this path. else: @@ -1641,16 +1590,14 @@ def test_yield_wait_does_not_shield_cancel(self): proof = 0 waiter = self.new_future(self.loop) - @asyncio.coroutine - def inner(): + async def inner(): nonlocal proof - yield from waiter + await waiter proof += 1 - @asyncio.coroutine - def outer(): + async def outer(): nonlocal proof - d, p = yield from asyncio.wait([inner()], loop=self.loop) + d, p = await asyncio.wait([inner()], loop=self.loop) proof += 100 f = asyncio.ensure_future(outer(), loop=self.loop) @@ -1697,16 +1644,14 @@ def test_shield_effect(self): proof = 0 waiter = self.new_future(self.loop) - @asyncio.coroutine - def inner(): + async def inner(): nonlocal proof - yield from waiter + await waiter proof += 1 - @asyncio.coroutine - def outer(): + async def outer(): nonlocal proof - yield from asyncio.shield(inner(), loop=self.loop) + await asyncio.shield(inner(), loop=self.loop) proof += 100 f = asyncio.ensure_future(outer(), loop=self.loop) @@ -1890,8 +1835,6 @@ def foo(): self.assertIsInstance(exception, Exception) self.assertEqual(exception.args, ("foo", )) - @unittest.skipUnless(PY34, - 'need python 3.4 or later') def test_log_destroyed_pending_task(self): Task = self.__class__.Task @@ -2661,5 +2604,47 @@ def coro(): self.assertEqual(result, 11) +class CompatibilityTests(test_utils.TestCase): + # Tests for checking a bridge between old-styled coroutines + # and async/await syntax + + def setUp(self): + super().setUp() + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(None) + + def tearDown(self): + self.loop.close() + self.loop = None + super().tearDown() + + def test_yield_from_awaitable(self): + + @asyncio.coroutine + def coro(): + yield from asyncio.sleep(0, loop=self.loop) + return 'ok' + + result = self.loop.run_until_complete(coro()) + self.assertEqual('ok', result) + + def test_await_old_style_coro(self): + + @asyncio.coroutine + def coro1(): + return 'ok1' + + @asyncio.coroutine + def coro2(): + yield from asyncio.sleep(0, loop=self.loop) + return 'ok2' + + async def inner(): + return await asyncio.gather(coro1(), coro2(), loop=self.loop) + + result = self.loop.run_until_complete(inner()) + self.assertEqual(['ok1', 'ok2'], result) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 284c73d8daf..6746b34fe2c 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -77,9 +77,8 @@ def test_add_signal_handler_setup_error(self, m_signal): def test_add_signal_handler_coroutine_error(self, m_signal): m_signal.NSIG = signal.NSIG - @asyncio.coroutine - def simple_coroutine(): - yield from [] + async def simple_coroutine(): + pass # callback must not be a coroutine function coro_func = simple_coroutine diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 5fdf5ff5e44..de6fe120612 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -56,14 +56,14 @@ def test_pipe(self): res = self.loop.run_until_complete(self._test_pipe()) self.assertEqual(res, 'done') - def _test_pipe(self): + async def _test_pipe(self): ADDRESS = r'\\.\pipe\_test_pipe-%s' % os.getpid() with self.assertRaises(FileNotFoundError): - yield from self.loop.create_pipe_connection( + await self.loop.create_pipe_connection( asyncio.Protocol, ADDRESS) - [server] = yield from self.loop.start_serving_pipe( + [server] = await self.loop.start_serving_pipe( UpperProto, ADDRESS) self.assertIsInstance(server, windows_events.PipeServer) @@ -72,7 +72,7 @@ def _test_pipe(self): stream_reader = asyncio.StreamReader(loop=self.loop) protocol = asyncio.StreamReaderProtocol(stream_reader, loop=self.loop) - trans, proto = yield from self.loop.create_pipe_connection( + trans, proto = await self.loop.create_pipe_connection( lambda: protocol, ADDRESS) self.assertIsInstance(trans, asyncio.Transport) self.assertEqual(protocol, proto) @@ -82,14 +82,14 @@ def _test_pipe(self): w.write('lower-{}\n'.format(i).encode()) for i, (r, w) in enumerate(clients): - response = yield from r.readline() + response = await r.readline() self.assertEqual(response, 'LOWER-{}\n'.format(i).encode()) w.close() server.close() with self.assertRaises(FileNotFoundError): - yield from self.loop.create_pipe_connection( + await self.loop.create_pipe_connection( asyncio.Protocol, ADDRESS) return 'done' @@ -97,7 +97,8 @@ def _test_pipe(self): def test_connect_pipe_cancel(self): exc = OSError() exc.winerror = _overlapped.ERROR_PIPE_BUSY - with mock.patch.object(_overlapped, 'ConnectPipe', side_effect=exc) as connect: + with mock.patch.object(_overlapped, 'ConnectPipe', + side_effect=exc) as connect: coro = self.loop._proactor.connect_pipe('pipe_address') task = self.loop.create_task(coro) diff --git a/Misc/NEWS.d/next/Library/2017-12-08-11-02-26.bpo-32193.NJe_TQ.rst b/Misc/NEWS.d/next/Library/2017-12-08-11-02-26.bpo-32193.NJe_TQ.rst new file mode 100644 index 00000000000..6982f1e1ac5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-08-11-02-26.bpo-32193.NJe_TQ.rst @@ -0,0 +1,2 @@ +Convert asyncio to use *async/await* syntax. Old styled ``yield from`` is +still supported too. From lp_benchmark_robot at intel.com Fri Dec 8 18:41:06 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 8 Dec 2017 15:41:06 -0800 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2017-12-08 Message-ID: Results for project python/master, build date: 2017-12-08 03:03:11-08:00. - commit: 11cc289 - previous commit: fb77e0d - revision date: 2017-12-07 16:24:59-08:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.951% | +0.297% | +4.999% | +7.966% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.982% | +0.066% | +21.939% | +13.662% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.193% | -0.303% | +22.778% | +12.551% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.657% | +0.518% | +21.412% | +12.739% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 4.345% | -0.678% | +7.445% | +10.095% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.689% | +0.234% | +11.019% | +9.311% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.506% | -0.028% | +7.012% | +10.213% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.421% | -0.049% | +0.371% | +8.348% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.816% | +0.219% | +9.112% | +16.476% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 4.389% | -1.194% | +10.775% | +15.412% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.011% | -0.215% | +4.261% | +7.675% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.225% | +0.087% | +5.546% | +4.454% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.781% | -0.054% | +2.511% | +6.039% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.152% | -0.204% | +13.549% | +9.294% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.295% | +0.204% | +9.471% | +8.586% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.950% | +0.027% | +5.343% | +11.643% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 1.187% | -0.128% | +10.296% | +11.285% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.334% | -0.101% | +8.606% | +9.548% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.255% | -0.258% | +3.367% | +7.884% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 2.415% | -0.068% | +0.553% | +10.670% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.807% | -0.124% | +5.997% | +13.301% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.758% | +0.269% | +46.740% | +14.509% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.556% | +0.074% | +7.143% | +14.866% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.841% | -0.108% | +16.662% | +13.543% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.971% | +0.085% | +5.961% | +10.782% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.850% | -0.456% | +4.060% | +5.098% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.611% | -0.066% | -1.553% | +0.211% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.642% | -0.246% | +4.678% | +7.584% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.197% | -0.190% | +6.128% | +9.493% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 3.066% | -0.486% | +0.676% | +18.604% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.565% | -0.044% | +0.284% | +22.096% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.863% | +0.179% | +0.014% | +23.587% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.792% | +0.441% | +9.816% | +11.051% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.138% | +0.056% | +0.357% | +10.156% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.142% | -0.049% | +10.488% | +4.979% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.105% | +0.006% | +1.870% | +5.140% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.333% | +0.241% | +9.614% | +13.195% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 6.020% | +2.218% | +2.819% | +9.864% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.338% | -0.055% | -1.473% | +11.359% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.600% | +0.191% | -5.526% | +6.672% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.426% | -0.046% | +3.983% | +8.838% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.525% | -0.125% | +7.569% | +14.299% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.627% | +0.081% | -3.297% | +3.991% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 2.467% | +0.097% | +27.241% | +7.631% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.631% | -0.068% | +4.490% | +5.367% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.686% | +0.160% | +14.543% | +8.349% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.342% | +0.614% | -4.886% | -1.301% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.483% | +0.087% | +3.278% | +4.546% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.074% | +0.146% | +6.710% | +6.764% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.302% | +0.133% | +6.579% | +4.778% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 6.559% | -3.093% | +18.223% | +8.348% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.248% | +0.097% | +11.162% | +8.083% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.825% | -0.422% | +8.868% | +7.149% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.483% | +0.234% | +11.274% | +8.066% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.068% | +0.127% | +10.693% | +9.208% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 6.402% | -2.003% | +20.135% | +14.693% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.153% | -0.054% | +5.944% | +7.128% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.316% | +0.320% | +1.438% | +1.300% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 5.985% | +0.892% | +4.419% | +21.894% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.272% | +0.932% | -1.037% | +16.627% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.076% | +0.280% | +7.989% | +5.400% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.062% | +0.081% | +5.705% | +8.547% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.316% | +0.023% | +3.311% | +7.287% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.196% | -0.618% | -7.097% | +13.260% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.501% | +0.255% | +7.357% | +7.807% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2017-12-08 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From solipsis at pitrou.net Sat Dec 9 04:08:15 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 09 Dec 2017 09:08:15 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171209090815.58595.40B55223EF2E7F98@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 1] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [-1, 2, -1] memory blocks, sum=0 test_multiprocessing_forkserver leaked [-2, 2, -1] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloggoC2kz', '--timeout', '7200'] From webhook-mailer at python.org Sat Dec 9 06:09:07 2017 From: webhook-mailer at python.org (Vinay Sajip) Date: Sat, 09 Dec 2017 11:09:07 -0000 Subject: [Python-checkins] bpo-32212: Updated logging documentation to make parameter names more consistent with source. (GH-4765) Message-ID: https://github.com/python/cpython/commit/a9f8df646aac7fc94ced0aefd1ed2c8566d14d10 commit: a9f8df646aac7fc94ced0aefd1ed2c8566d14d10 branch: master author: Vinay Sajip committer: GitHub date: 2017-12-09T11:09:04Z summary: bpo-32212: Updated logging documentation to make parameter names more consistent with source. (GH-4765) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 148f131cac5..1ed129c00d4 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -91,12 +91,12 @@ is the module's name in the Python package namespace. scenario is to attach handlers only to the root logger, and to let propagation take care of the rest. - .. method:: Logger.setLevel(lvl) + .. method:: Logger.setLevel(level) - Sets the threshold for this logger to *lvl*. Logging messages which are less - severe than *lvl* will be ignored; logging messages which have severity *lvl* + Sets the threshold for this logger to *level*. Logging messages which are less + severe than *level* will be ignored; logging messages which have severity *level* or higher will be emitted by whichever handler or handlers service this logger, - unless a handler's level has been set to a higher severity level than *lvl*. + unless a handler's level has been set to a higher severity level than *level*. When a logger is created, the level is set to :const:`NOTSET` (which causes all messages to be processed when the logger is the root logger, or delegation @@ -117,7 +117,7 @@ is the module's name in the Python package namespace. See :ref:`levels` for a list of levels. .. versionchanged:: 3.2 - The *lvl* parameter now accepts a string representation of the + The *level* parameter now accepts a string representation of the level such as 'INFO' as an alternative to the integer constants such as :const:`INFO`. Note, however, that levels are internally stored as integers, and methods such as e.g. :meth:`getEffectiveLevel` and @@ -267,14 +267,14 @@ is the module's name in the Python package namespace. message. This method should only be called from an exception handler. - .. method:: Logger.addFilter(filt) + .. method:: Logger.addFilter(filter) - Adds the specified filter *filt* to this logger. + Adds the specified filter *filter* to this logger. - .. method:: Logger.removeFilter(filt) + .. method:: Logger.removeFilter(filter) - Removes the specified filter *filt* from this logger. + Removes the specified filter *filter* from this logger. .. method:: Logger.filter(record) @@ -393,33 +393,34 @@ subclasses. However, the :meth:`__init__` method in subclasses needs to call Releases the thread lock acquired with :meth:`acquire`. - .. method:: Handler.setLevel(lvl) + .. method:: Handler.setLevel(level) - Sets the threshold for this handler to *lvl*. Logging messages which are less - severe than *lvl* will be ignored. When a handler is created, the level is set - to :const:`NOTSET` (which causes all messages to be processed). + Sets the threshold for this handler to *level*. Logging messages which are + less severe than *level* will be ignored. When a handler is created, the + level is set to :const:`NOTSET` (which causes all messages to be + processed). See :ref:`levels` for a list of levels. .. versionchanged:: 3.2 - The *lvl* parameter now accepts a string representation of the + The *level* parameter now accepts a string representation of the level such as 'INFO' as an alternative to the integer constants such as :const:`INFO`. - .. method:: Handler.setFormatter(form) + .. method:: Handler.setFormatter(fmt) - Sets the :class:`Formatter` for this handler to *form*. + Sets the :class:`Formatter` for this handler to *fmt*. - .. method:: Handler.addFilter(filt) + .. method:: Handler.addFilter(filter) - Adds the specified filter *filt* to this handler. + Adds the specified filter *filter* to this handler. - .. method:: Handler.removeFilter(filt) + .. method:: Handler.removeFilter(filter) - Removes the specified filter *filt* from this handler. + Removes the specified filter *filter* from this handler. .. method:: Handler.filter(record) From webhook-mailer at python.org Sat Dec 9 07:28:19 2017 From: webhook-mailer at python.org (Vinay Sajip) Date: Sat, 09 Dec 2017 12:28:19 -0000 Subject: [Python-checkins] bpo-32212: Updated logging documentation to make parameter names more consistent with source. (GH-4765) (GH-4767) Message-ID: https://github.com/python/cpython/commit/63868181a904c844d8d01e3badfdd5b134acc5fa commit: 63868181a904c844d8d01e3badfdd5b134acc5fa branch: 3.6 author: Vinay Sajip committer: GitHub date: 2017-12-09T12:28:16Z summary: bpo-32212: Updated logging documentation to make parameter names more consistent with source. (GH-4765) (GH-4767) (cherry picked from commit a9f8df646aac7fc94ced0aefd1ed2c8566d14d10) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 6098878c1a1..1ed129c00d4 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -69,260 +69,266 @@ is the module's name in the Python package namespace. .. class:: Logger -.. attribute:: Logger.propagate + .. attribute:: Logger.propagate - If this evaluates to true, events logged to this logger will be passed to the - handlers of higher level (ancestor) loggers, in addition to any handlers - attached to this logger. Messages are passed directly to the ancestor - loggers' handlers - neither the level nor filters of the ancestor loggers in - question are considered. + If this attribute evaluates to true, events logged to this logger will be + passed to the handlers of higher level (ancestor) loggers, in addition to + any handlers attached to this logger. Messages are passed directly to the + ancestor loggers' handlers - neither the level nor filters of the ancestor + loggers in question are considered. - If this evaluates to false, logging messages are not passed to the handlers - of ancestor loggers. + If this evaluates to false, logging messages are not passed to the handlers + of ancestor loggers. - The constructor sets this attribute to ``True``. + The constructor sets this attribute to ``True``. - .. note:: If you attach a handler to a logger *and* one or more of its - ancestors, it may emit the same record multiple times. In general, you - should not need to attach a handler to more than one logger - if you just - attach it to the appropriate logger which is highest in the logger - hierarchy, then it will see all events logged by all descendant loggers, - provided that their propagate setting is left set to ``True``. A common - scenario is to attach handlers only to the root logger, and to let - propagation take care of the rest. + .. note:: If you attach a handler to a logger *and* one or more of its + ancestors, it may emit the same record multiple times. In general, you + should not need to attach a handler to more than one logger - if you just + attach it to the appropriate logger which is highest in the logger + hierarchy, then it will see all events logged by all descendant loggers, + provided that their propagate setting is left set to ``True``. A common + scenario is to attach handlers only to the root logger, and to let + propagation take care of the rest. -.. method:: Logger.setLevel(lvl) + .. method:: Logger.setLevel(level) - Sets the threshold for this logger to *lvl*. Logging messages which are less - severe than *lvl* will be ignored. When a logger is created, the level is set to - :const:`NOTSET` (which causes all messages to be processed when the logger is - the root logger, or delegation to the parent when the logger is a non-root - logger). Note that the root logger is created with level :const:`WARNING`. + Sets the threshold for this logger to *level*. Logging messages which are less + severe than *level* will be ignored; logging messages which have severity *level* + or higher will be emitted by whichever handler or handlers service this logger, + unless a handler's level has been set to a higher severity level than *level*. - The term 'delegation to the parent' means that if a logger has a level of - NOTSET, its chain of ancestor loggers is traversed until either an ancestor with - a level other than NOTSET is found, or the root is reached. + When a logger is created, the level is set to :const:`NOTSET` (which causes + all messages to be processed when the logger is the root logger, or delegation + to the parent when the logger is a non-root logger). Note that the root logger + is created with level :const:`WARNING`. - If an ancestor is found with a level other than NOTSET, then that ancestor's - level is treated as the effective level of the logger where the ancestor search - began, and is used to determine how a logging event is handled. + The term 'delegation to the parent' means that if a logger has a level of + NOTSET, its chain of ancestor loggers is traversed until either an ancestor with + a level other than NOTSET is found, or the root is reached. - If the root is reached, and it has a level of NOTSET, then all messages will be - processed. Otherwise, the root's level will be used as the effective level. + If an ancestor is found with a level other than NOTSET, then that ancestor's + level is treated as the effective level of the logger where the ancestor search + began, and is used to determine how a logging event is handled. - See :ref:`levels` for a list of levels. + If the root is reached, and it has a level of NOTSET, then all messages will be + processed. Otherwise, the root's level will be used as the effective level. - .. versionchanged:: 3.2 - The *lvl* parameter now accepts a string representation of the - level such as 'INFO' as an alternative to the integer constants - such as :const:`INFO`. Note, however, that levels are internally stored - as integers, and methods such as e.g. :meth:`getEffectiveLevel` and - :meth:`isEnabledFor` will return/expect to be passed integers. + See :ref:`levels` for a list of levels. + .. versionchanged:: 3.2 + The *level* parameter now accepts a string representation of the + level such as 'INFO' as an alternative to the integer constants + such as :const:`INFO`. Note, however, that levels are internally stored + as integers, and methods such as e.g. :meth:`getEffectiveLevel` and + :meth:`isEnabledFor` will return/expect to be passed integers. -.. method:: Logger.isEnabledFor(lvl) - Indicates if a message of severity *lvl* would be processed by this logger. - This method checks first the module-level level set by - ``logging.disable(lvl)`` and then the logger's effective level as determined - by :meth:`getEffectiveLevel`. + .. method:: Logger.isEnabledFor(lvl) + Indicates if a message of severity *lvl* would be processed by this logger. + This method checks first the module-level level set by + ``logging.disable(lvl)`` and then the logger's effective level as determined + by :meth:`getEffectiveLevel`. -.. method:: Logger.getEffectiveLevel() - Indicates the effective level for this logger. If a value other than - :const:`NOTSET` has been set using :meth:`setLevel`, it is returned. Otherwise, - the hierarchy is traversed towards the root until a value other than - :const:`NOTSET` is found, and that value is returned. The value returned is - an integer, typically one of :const:`logging.DEBUG`, :const:`logging.INFO` - etc. + .. method:: Logger.getEffectiveLevel() + Indicates the effective level for this logger. If a value other than + :const:`NOTSET` has been set using :meth:`setLevel`, it is returned. Otherwise, + the hierarchy is traversed towards the root until a value other than + :const:`NOTSET` is found, and that value is returned. The value returned is + an integer, typically one of :const:`logging.DEBUG`, :const:`logging.INFO` + etc. -.. method:: Logger.getChild(suffix) - Returns a logger which is a descendant to this logger, as determined by the suffix. - Thus, ``logging.getLogger('abc').getChild('def.ghi')`` would return the same - logger as would be returned by ``logging.getLogger('abc.def.ghi')``. This is a - convenience method, useful when the parent logger is named using e.g. ``__name__`` - rather than a literal string. + .. method:: Logger.getChild(suffix) - .. versionadded:: 3.2 + Returns a logger which is a descendant to this logger, as determined by the suffix. + Thus, ``logging.getLogger('abc').getChild('def.ghi')`` would return the same + logger as would be returned by ``logging.getLogger('abc.def.ghi')``. This is a + convenience method, useful when the parent logger is named using e.g. ``__name__`` + rather than a literal string. + .. versionadded:: 3.2 -.. method:: Logger.debug(msg, *args, **kwargs) - Logs a message with level :const:`DEBUG` on this logger. The *msg* is the - message format string, and the *args* are the arguments which are merged into - *msg* using the string formatting operator. (Note that this means that you can - use keywords in the format string, together with a single dictionary argument.) + .. method:: Logger.debug(msg, *args, **kwargs) - There are three keyword arguments in *kwargs* which are inspected: - *exc_info*, *stack_info*, and *extra*. + Logs a message with level :const:`DEBUG` on this logger. The *msg* is the + message format string, and the *args* are the arguments which are merged into + *msg* using the string formatting operator. (Note that this means that you can + use keywords in the format string, together with a single dictionary argument.) - If *exc_info* does not evaluate as false, it causes exception information to be - added to the logging message. If an exception tuple (in the format returned by - :func:`sys.exc_info`) or an exception instance is provided, it is used; - otherwise, :func:`sys.exc_info` is called to get the exception information. + There are three keyword arguments in *kwargs* which are inspected: + *exc_info*, *stack_info*, and *extra*. - The second optional keyword argument is *stack_info*, which defaults to - ``False``. If true, stack information is added to the logging - message, including the actual logging call. Note that this is not the same - stack information as that displayed through specifying *exc_info*: The - former is stack frames from the bottom of the stack up to the logging call - in the current thread, whereas the latter is information about stack frames - which have been unwound, following an exception, while searching for - exception handlers. + If *exc_info* does not evaluate as false, it causes exception information to be + added to the logging message. If an exception tuple (in the format returned by + :func:`sys.exc_info`) or an exception instance is provided, it is used; + otherwise, :func:`sys.exc_info` is called to get the exception information. - You can specify *stack_info* independently of *exc_info*, e.g. to just show - how you got to a certain point in your code, even when no exceptions were - raised. The stack frames are printed following a header line which says:: + The second optional keyword argument is *stack_info*, which defaults to + ``False``. If true, stack information is added to the logging + message, including the actual logging call. Note that this is not the same + stack information as that displayed through specifying *exc_info*: The + former is stack frames from the bottom of the stack up to the logging call + in the current thread, whereas the latter is information about stack frames + which have been unwound, following an exception, while searching for + exception handlers. - Stack (most recent call last): + You can specify *stack_info* independently of *exc_info*, e.g. to just show + how you got to a certain point in your code, even when no exceptions were + raised. The stack frames are printed following a header line which says:: - This mimics the ``Traceback (most recent call last):`` which is used when - displaying exception frames. + Stack (most recent call last): - The third keyword argument is *extra* which can be used to pass a - dictionary which is used to populate the __dict__ of the LogRecord created for - the logging event with user-defined attributes. These custom attributes can then - be used as you like. For example, they could be incorporated into logged - messages. For example:: + This mimics the ``Traceback (most recent call last):`` which is used when + displaying exception frames. - FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s' - logging.basicConfig(format=FORMAT) - d = {'clientip': '192.168.0.1', 'user': 'fbloggs'} - logger = logging.getLogger('tcpserver') - logger.warning('Protocol problem: %s', 'connection reset', extra=d) + The third keyword argument is *extra* which can be used to pass a + dictionary which is used to populate the __dict__ of the LogRecord created for + the logging event with user-defined attributes. These custom attributes can then + be used as you like. For example, they could be incorporated into logged + messages. For example:: - would print something like :: + FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s' + logging.basicConfig(format=FORMAT) + d = {'clientip': '192.168.0.1', 'user': 'fbloggs'} + logger = logging.getLogger('tcpserver') + logger.warning('Protocol problem: %s', 'connection reset', extra=d) - 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset + would print something like :: - The keys in the dictionary passed in *extra* should not clash with the keys used - by the logging system. (See the :class:`Formatter` documentation for more - information on which keys are used by the logging system.) + 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset - If you choose to use these attributes in logged messages, you need to exercise - some care. In the above example, for instance, the :class:`Formatter` has been - set up with a format string which expects 'clientip' and 'user' in the attribute - dictionary of the LogRecord. If these are missing, the message will not be - logged because a string formatting exception will occur. So in this case, you - always need to pass the *extra* dictionary with these keys. + The keys in the dictionary passed in *extra* should not clash with the keys used + by the logging system. (See the :class:`Formatter` documentation for more + information on which keys are used by the logging system.) - While this might be annoying, this feature is intended for use in specialized - circumstances, such as multi-threaded servers where the same code executes in - many contexts, and interesting conditions which arise are dependent on this - context (such as remote client IP address and authenticated user name, in the - above example). In such circumstances, it is likely that specialized - :class:`Formatter`\ s would be used with particular :class:`Handler`\ s. + If you choose to use these attributes in logged messages, you need to exercise + some care. In the above example, for instance, the :class:`Formatter` has been + set up with a format string which expects 'clientip' and 'user' in the attribute + dictionary of the LogRecord. If these are missing, the message will not be + logged because a string formatting exception will occur. So in this case, you + always need to pass the *extra* dictionary with these keys. - .. versionadded:: 3.2 - The *stack_info* parameter was added. + While this might be annoying, this feature is intended for use in specialized + circumstances, such as multi-threaded servers where the same code executes in + many contexts, and interesting conditions which arise are dependent on this + context (such as remote client IP address and authenticated user name, in the + above example). In such circumstances, it is likely that specialized + :class:`Formatter`\ s would be used with particular :class:`Handler`\ s. - .. versionchanged:: 3.5 - The *exc_info* parameter can now accept exception instances. + .. versionadded:: 3.2 + The *stack_info* parameter was added. + .. versionchanged:: 3.5 + The *exc_info* parameter can now accept exception instances. -.. method:: Logger.info(msg, *args, **kwargs) - Logs a message with level :const:`INFO` on this logger. The arguments are - interpreted as for :meth:`debug`. + .. method:: Logger.info(msg, *args, **kwargs) + Logs a message with level :const:`INFO` on this logger. The arguments are + interpreted as for :meth:`debug`. -.. method:: Logger.warning(msg, *args, **kwargs) - Logs a message with level :const:`WARNING` on this logger. The arguments are - interpreted as for :meth:`debug`. + .. method:: Logger.warning(msg, *args, **kwargs) - .. note:: There is an obsolete method ``warn`` which is functionally - identical to ``warning``. As ``warn`` is deprecated, please do not use - it - use ``warning`` instead. + Logs a message with level :const:`WARNING` on this logger. The arguments are + interpreted as for :meth:`debug`. -.. method:: Logger.error(msg, *args, **kwargs) + .. note:: There is an obsolete method ``warn`` which is functionally + identical to ``warning``. As ``warn`` is deprecated, please do not use + it - use ``warning`` instead. - Logs a message with level :const:`ERROR` on this logger. The arguments are - interpreted as for :meth:`debug`. + .. method:: Logger.error(msg, *args, **kwargs) + Logs a message with level :const:`ERROR` on this logger. The arguments are + interpreted as for :meth:`debug`. -.. method:: Logger.critical(msg, *args, **kwargs) - Logs a message with level :const:`CRITICAL` on this logger. The arguments are - interpreted as for :meth:`debug`. + .. method:: Logger.critical(msg, *args, **kwargs) + Logs a message with level :const:`CRITICAL` on this logger. The arguments are + interpreted as for :meth:`debug`. -.. method:: Logger.log(lvl, msg, *args, **kwargs) - Logs a message with integer level *lvl* on this logger. The other arguments are - interpreted as for :meth:`debug`. + .. method:: Logger.log(lvl, msg, *args, **kwargs) + Logs a message with integer level *lvl* on this logger. The other arguments are + interpreted as for :meth:`debug`. -.. method:: Logger.exception(msg, *args, **kwargs) - Logs a message with level :const:`ERROR` on this logger. The arguments are - interpreted as for :meth:`debug`. Exception info is added to the logging - message. This method should only be called from an exception handler. + .. method:: Logger.exception(msg, *args, **kwargs) + Logs a message with level :const:`ERROR` on this logger. The arguments are + interpreted as for :meth:`debug`. Exception info is added to the logging + message. This method should only be called from an exception handler. -.. method:: Logger.addFilter(filt) - Adds the specified filter *filt* to this logger. + .. method:: Logger.addFilter(filter) + Adds the specified filter *filter* to this logger. -.. method:: Logger.removeFilter(filt) - Removes the specified filter *filt* from this logger. + .. method:: Logger.removeFilter(filter) + Removes the specified filter *filter* from this logger. -.. method:: Logger.filter(record) - Applies this logger's filters to the record and returns a true value if the - record is to be processed. The filters are consulted in turn, until one of - them returns a false value. If none of them return a false value, the record - will be processed (passed to handlers). If one returns a false value, no - further processing of the record occurs. + .. method:: Logger.filter(record) + Applies this logger's filters to the record and returns a true value if the + record is to be processed. The filters are consulted in turn, until one of + them returns a false value. If none of them return a false value, the record + will be processed (passed to handlers). If one returns a false value, no + further processing of the record occurs. -.. method:: Logger.addHandler(hdlr) - Adds the specified handler *hdlr* to this logger. + .. method:: Logger.addHandler(hdlr) + Adds the specified handler *hdlr* to this logger. -.. method:: Logger.removeHandler(hdlr) - Removes the specified handler *hdlr* from this logger. + .. method:: Logger.removeHandler(hdlr) + Removes the specified handler *hdlr* from this logger. -.. method:: Logger.findCaller(stack_info=False) - Finds the caller's source filename and line number. Returns the filename, line - number, function name and stack information as a 4-element tuple. The stack - information is returned as ``None`` unless *stack_info* is ``True``. + .. method:: Logger.findCaller(stack_info=False) + Finds the caller's source filename and line number. Returns the filename, line + number, function name and stack information as a 4-element tuple. The stack + information is returned as ``None`` unless *stack_info* is ``True``. -.. method:: Logger.handle(record) - Handles a record by passing it to all handlers associated with this logger and - its ancestors (until a false value of *propagate* is found). This method is used - for unpickled records received from a socket, as well as those created locally. - Logger-level filtering is applied using :meth:`~Logger.filter`. + .. method:: Logger.handle(record) + Handles a record by passing it to all handlers associated with this logger and + its ancestors (until a false value of *propagate* is found). This method is used + for unpickled records received from a socket, as well as those created locally. + Logger-level filtering is applied using :meth:`~Logger.filter`. -.. method:: Logger.makeRecord(name, lvl, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None) - This is a factory method which can be overridden in subclasses to create - specialized :class:`LogRecord` instances. + .. method:: Logger.makeRecord(name, lvl, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None) -.. method:: Logger.hasHandlers() + This is a factory method which can be overridden in subclasses to create + specialized :class:`LogRecord` instances. - Checks to see if this logger has any handlers configured. This is done by - looking for handlers in this logger and its parents in the logger hierarchy. - Returns ``True`` if a handler was found, else ``False``. The method stops searching - up the hierarchy whenever a logger with the 'propagate' attribute set to - false is found - that will be the last logger which is checked for the - existence of handlers. + .. method:: Logger.hasHandlers() - .. versionadded:: 3.2 + Checks to see if this logger has any handlers configured. This is done by + looking for handlers in this logger and its parents in the logger hierarchy. + Returns ``True`` if a handler was found, else ``False``. The method stops searching + up the hierarchy whenever a logger with the 'propagate' attribute set to + false is found - that will be the last logger which is checked for the + existence of handlers. + .. versionadded:: 3.2 + + .. versionchanged:: 3.7 + Loggers can now be picked and unpickled. .. _levels: @@ -362,113 +368,115 @@ is never instantiated directly; this class acts as a base for more useful subclasses. However, the :meth:`__init__` method in subclasses needs to call :meth:`Handler.__init__`. +.. class:: Handler -.. method:: Handler.__init__(level=NOTSET) + .. method:: Handler.__init__(level=NOTSET) - Initializes the :class:`Handler` instance by setting its level, setting the list - of filters to the empty list and creating a lock (using :meth:`createLock`) for - serializing access to an I/O mechanism. + Initializes the :class:`Handler` instance by setting its level, setting the list + of filters to the empty list and creating a lock (using :meth:`createLock`) for + serializing access to an I/O mechanism. -.. method:: Handler.createLock() + .. method:: Handler.createLock() - Initializes a thread lock which can be used to serialize access to underlying - I/O functionality which may not be threadsafe. + Initializes a thread lock which can be used to serialize access to underlying + I/O functionality which may not be threadsafe. -.. method:: Handler.acquire() + .. method:: Handler.acquire() - Acquires the thread lock created with :meth:`createLock`. + Acquires the thread lock created with :meth:`createLock`. -.. method:: Handler.release() + .. method:: Handler.release() - Releases the thread lock acquired with :meth:`acquire`. + Releases the thread lock acquired with :meth:`acquire`. -.. method:: Handler.setLevel(lvl) + .. method:: Handler.setLevel(level) - Sets the threshold for this handler to *lvl*. Logging messages which are less - severe than *lvl* will be ignored. When a handler is created, the level is set - to :const:`NOTSET` (which causes all messages to be processed). + Sets the threshold for this handler to *level*. Logging messages which are + less severe than *level* will be ignored. When a handler is created, the + level is set to :const:`NOTSET` (which causes all messages to be + processed). - See :ref:`levels` for a list of levels. + See :ref:`levels` for a list of levels. - .. versionchanged:: 3.2 - The *lvl* parameter now accepts a string representation of the - level such as 'INFO' as an alternative to the integer constants - such as :const:`INFO`. + .. versionchanged:: 3.2 + The *level* parameter now accepts a string representation of the + level such as 'INFO' as an alternative to the integer constants + such as :const:`INFO`. -.. method:: Handler.setFormatter(form) + .. method:: Handler.setFormatter(fmt) - Sets the :class:`Formatter` for this handler to *form*. + Sets the :class:`Formatter` for this handler to *fmt*. -.. method:: Handler.addFilter(filt) + .. method:: Handler.addFilter(filter) - Adds the specified filter *filt* to this handler. + Adds the specified filter *filter* to this handler. -.. method:: Handler.removeFilter(filt) + .. method:: Handler.removeFilter(filter) - Removes the specified filter *filt* from this handler. + Removes the specified filter *filter* from this handler. -.. method:: Handler.filter(record) + .. method:: Handler.filter(record) - Applies this handler's filters to the record and returns a true value if the - record is to be processed. The filters are consulted in turn, until one of - them returns a false value. If none of them return a false value, the record - will be emitted. If one returns a false value, the handler will not emit the - record. + Applies this handler's filters to the record and returns a true value if the + record is to be processed. The filters are consulted in turn, until one of + them returns a false value. If none of them return a false value, the record + will be emitted. If one returns a false value, the handler will not emit the + record. -.. method:: Handler.flush() + .. method:: Handler.flush() - Ensure all logging output has been flushed. This version does nothing and is - intended to be implemented by subclasses. + Ensure all logging output has been flushed. This version does nothing and is + intended to be implemented by subclasses. -.. method:: Handler.close() + .. method:: Handler.close() - Tidy up any resources used by the handler. This version does no output but - removes the handler from an internal list of handlers which is closed when - :func:`shutdown` is called. Subclasses should ensure that this gets called - from overridden :meth:`close` methods. + Tidy up any resources used by the handler. This version does no output but + removes the handler from an internal list of handlers which is closed when + :func:`shutdown` is called. Subclasses should ensure that this gets called + from overridden :meth:`close` methods. -.. method:: Handler.handle(record) + .. method:: Handler.handle(record) - Conditionally emits the specified logging record, depending on filters which may - have been added to the handler. Wraps the actual emission of the record with - acquisition/release of the I/O thread lock. + Conditionally emits the specified logging record, depending on filters which may + have been added to the handler. Wraps the actual emission of the record with + acquisition/release of the I/O thread lock. -.. method:: Handler.handleError(record) + .. method:: Handler.handleError(record) - This method should be called from handlers when an exception is encountered - during an :meth:`emit` call. If the module-level attribute - ``raiseExceptions`` is ``False``, exceptions get silently ignored. This is - what is mostly wanted for a logging system - most users will not care about - errors in the logging system, they are more interested in application - errors. You could, however, replace this with a custom handler if you wish. - The specified record is the one which was being processed when the exception - occurred. (The default value of ``raiseExceptions`` is ``True``, as that is - more useful during development). + This method should be called from handlers when an exception is encountered + during an :meth:`emit` call. If the module-level attribute + ``raiseExceptions`` is ``False``, exceptions get silently ignored. This is + what is mostly wanted for a logging system - most users will not care about + errors in the logging system, they are more interested in application + errors. You could, however, replace this with a custom handler if you wish. + The specified record is the one which was being processed when the exception + occurred. (The default value of ``raiseExceptions`` is ``True``, as that is + more useful during development). -.. method:: Handler.format(record) + .. method:: Handler.format(record) - Do formatting for a record - if a formatter is set, use it. Otherwise, use the - default formatter for the module. + Do formatting for a record - if a formatter is set, use it. Otherwise, use the + default formatter for the module. -.. method:: Handler.emit(record) + .. method:: Handler.emit(record) - Do whatever it takes to actually log the specified logging record. This version - is intended to be implemented by subclasses and so raises a - :exc:`NotImplementedError`. + Do whatever it takes to actually log the specified logging record. This version + is intended to be implemented by subclasses and so raises a + :exc:`NotImplementedError`. For a list of handlers included as standard, see :mod:`logging.handlers`. @@ -772,15 +780,15 @@ the options available to you. | lineno | ``%(lineno)d`` | Source line number where the logging call was | | | | issued (if available). | +----------------+-------------------------+-----------------------------------------------+ +| message | ``%(message)s`` | The logged message, computed as ``msg % | +| | | args``. This is set when | +| | | :meth:`Formatter.format` is invoked. | ++----------------+-------------------------+-----------------------------------------------+ | module | ``%(module)s`` | Module (name portion of ``filename``). | +----------------+-------------------------+-----------------------------------------------+ | msecs | ``%(msecs)d`` | Millisecond portion of the time when the | | | | :class:`LogRecord` was created. | +----------------+-------------------------+-----------------------------------------------+ -| message | ``%(message)s`` | The logged message, computed as ``msg % | -| | | args``. This is set when | -| | | :meth:`Formatter.format` is invoked. | -+----------------+-------------------------+-----------------------------------------------+ | msg | You shouldn't need to | The format string passed in the original | | | format this yourself. | logging call. Merged with ``args`` to | | | | produce ``message``, or an arbitrary object | @@ -1023,7 +1031,7 @@ functions. handlers being added multiple times to the root logger, which can in turn lead to multiple messages for the same event. -.. function:: disable(lvl) +.. function:: disable(lvl=CRITICAL) Provides an overriding level *lvl* for all loggers which takes precedence over the logger's own level. When the need arises to temporarily throttle logging @@ -1036,6 +1044,14 @@ functions. overriding level, so that logging output again depends on the effective levels of individual loggers. + Note that if you have defined any custom logging level higher than + ``CRITICAL`` (this is not recommended), you won't be able to rely on the + default value for the *lvl* parameter, but will have to explicitly supply a + suitable value. + + .. versionchanged:: 3.7 + The *lvl* parameter was defaulted to level ``CRITICAL``. See Issue + #28524 for more information about this change. .. function:: addLevelName(lvl, levelName) @@ -1248,4 +1264,3 @@ with the :mod:`warnings` module. package available from this site is suitable for use with Python 1.5.2, 2.1.x and 2.2.x, which do not include the :mod:`logging` package in the standard library. - From webhook-mailer at python.org Sat Dec 9 07:49:15 2017 From: webhook-mailer at python.org (Vinay Sajip) Date: Sat, 09 Dec 2017 12:49:15 -0000 Subject: [Python-checkins] bpo-32212: Updated logging documentation to make parameter names more consistent with source. (GH-4765) (GH-4768) Message-ID: https://github.com/python/cpython/commit/292fce9934280867ca9a65870495f83fca37751e commit: 292fce9934280867ca9a65870495f83fca37751e branch: 2.7 author: Vinay Sajip committer: GitHub date: 2017-12-09T12:49:10Z summary: bpo-32212: Updated logging documentation to make parameter names more consistent with source. (GH-4765) (GH-4768) (cherry picked from commit a9f8df646aac7fc94ced0aefd1ed2c8566d14d10) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index ba2ab835fd4..0f568aaa976 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -95,10 +95,10 @@ is the module's name in the Python package namespace. scenario is to attach handlers only to the root logger, and to let propagation take care of the rest. -.. method:: Logger.setLevel(lvl) +.. method:: Logger.setLevel(level) - Sets the threshold for this logger to *lvl*. Logging messages which are less - severe than *lvl* will be ignored. When a logger is created, the level is set to + Sets the threshold for this logger to *level*. Logging messages which are less + severe than *level* will be ignored. When a logger is created, the level is set to :const:`NOTSET` (which causes all messages to be processed when the logger is the root logger, or delegation to the parent when the logger is a non-root logger). Note that the root logger is created with level :const:`WARNING`. @@ -232,14 +232,14 @@ is the module's name in the Python package namespace. should only be called from an exception handler. -.. method:: Logger.addFilter(filt) +.. method:: Logger.addFilter(filter) - Adds the specified filter *filt* to this logger. + Adds the specified filter *filter* to this logger. -.. method:: Logger.removeFilter(filt) +.. method:: Logger.removeFilter(filter) - Removes the specified filter *filt* from this logger. + Removes the specified filter *filter* from this logger. .. method:: Logger.filter(record) @@ -349,27 +349,27 @@ subclasses. However, the :meth:`__init__` method in subclasses needs to call Releases the thread lock acquired with :meth:`acquire`. -.. method:: Handler.setLevel(lvl) +.. method:: Handler.setLevel(level) - Sets the threshold for this handler to *lvl*. Logging messages which are less - severe than *lvl* will be ignored. When a handler is created, the level is set + Sets the threshold for this handler to *level*. Logging messages which are less + severe than *level* will be ignored. When a handler is created, the level is set to :const:`NOTSET` (which causes all messages to be processed). See :ref:`levels` for a list of levels. -.. method:: Handler.setFormatter(form) +.. method:: Handler.setFormatter(fmt) - Sets the :class:`Formatter` for this handler to *form*. + Sets the :class:`Formatter` for this handler to *fmt*. -.. method:: Handler.addFilter(filt) +.. method:: Handler.addFilter(filter) - Adds the specified filter *filt* to this handler. + Adds the specified filter *filter* to this handler. -.. method:: Handler.removeFilter(filt) +.. method:: Handler.removeFilter(filter) - Removes the specified filter *filt* from this handler. + Removes the specified filter *filter* from this handler. .. method:: Handler.filter(record) From webhook-mailer at python.org Sat Dec 9 13:00:08 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 09 Dec 2017 18:00:08 -0000 Subject: [Python-checkins] bpo-32253: Deprecate with statement and bare await for asyncio locks (GH-4764) Message-ID: https://github.com/python/cpython/commit/28d8d14013ade0657fed4673f5fa3c08eb2b1944 commit: 28d8d14013ade0657fed4673f5fa3c08eb2b1944 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-09T20:00:05+02:00 summary: bpo-32253: Deprecate with statement and bare await for asyncio locks (GH-4764) * Add test for 'with (yield from lock)' * Deprecate with statement for asyncio locks * Document the deprecation files: A Misc/NEWS.d/next/Library/2017-12-09-11-30-35.bpo-32253.TQHSYF.rst M Doc/library/asyncio-sync.rst M Lib/asyncio/locks.py M Lib/test/test_asyncio/test_locks.py M Lib/test/test_asyncio/test_pep492.py diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst index 14e3defbf41..3e574f41e80 100644 --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -23,11 +23,9 @@ module (:class:`~threading.Lock`, :class:`~threading.Event`, :class:`~threading.BoundedSemaphore`), but it has no *timeout* parameter. The :func:`asyncio.wait_for` function can be used to cancel a task after a timeout. -Locks ------ Lock -^^^^ +---- .. class:: Lock(\*, loop=None) @@ -37,8 +35,9 @@ Lock particular coroutine when locked. A primitive lock is in one of two states, 'locked' or 'unlocked'. - It is created in the unlocked state. It has two basic methods, :meth:`acquire` - and :meth:`release`. When the state is unlocked, acquire() changes the state to + The lock is created in the unlocked state. + It has two basic methods, :meth:`acquire` and :meth:`release`. + When the state is unlocked, acquire() changes the state to locked and returns immediately. When the state is locked, acquire() blocks until a call to release() in another coroutine changes it to unlocked, then the acquire() call resets it to locked and returns. The release() method @@ -51,38 +50,12 @@ Lock resets the state to unlocked; first coroutine which is blocked in acquire() is being processed. - :meth:`acquire` is a coroutine and should be called with ``yield from``. + :meth:`acquire` is a coroutine and should be called with ``await``. - Locks also support the context management protocol. ``(yield from lock)`` - should be used as the context manager expression. + Locks support the :ref:`context management protocol `. This class is :ref:`not thread safe `. - Usage:: - - lock = Lock() - ... - yield from lock - try: - ... - finally: - lock.release() - - Context manager usage:: - - lock = Lock() - ... - with (yield from lock): - ... - - Lock objects can be tested for locking state:: - - if not lock.locked(): - yield from lock - else: - # lock is acquired - ... - .. method:: locked() Return ``True`` if the lock is acquired. @@ -110,7 +83,7 @@ Lock Event -^^^^^ +----- .. class:: Event(\*, loop=None) @@ -151,7 +124,7 @@ Event Condition -^^^^^^^^^ +--------- .. class:: Condition(lock=None, \*, loop=None) @@ -166,6 +139,9 @@ Condition object, and it is used as the underlying lock. Otherwise, a new :class:`Lock` object is created and used as the underlying lock. + Conditions support the :ref:`context management protocol + `. + This class is :ref:`not thread safe `. .. coroutinemethod:: acquire() @@ -239,11 +215,8 @@ Condition This method is a :ref:`coroutine `. -Semaphores ----------- - Semaphore -^^^^^^^^^ +--------- .. class:: Semaphore(value=1, \*, loop=None) @@ -254,12 +227,13 @@ Semaphore counter can never go below zero; when :meth:`acquire` finds that it is zero, it blocks, waiting until some other coroutine calls :meth:`release`. - Semaphores also support the context management protocol. - The optional argument gives the initial value for the internal counter; it defaults to ``1``. If the value given is less than ``0``, :exc:`ValueError` is raised. + Semaphores support the :ref:`context management protocol + `. + This class is :ref:`not thread safe `. .. coroutinemethod:: acquire() @@ -285,7 +259,7 @@ Semaphore BoundedSemaphore -^^^^^^^^^^^^^^^^ +---------------- .. class:: BoundedSemaphore(value=1, \*, loop=None) @@ -293,3 +267,39 @@ BoundedSemaphore This raises :exc:`ValueError` in :meth:`~Semaphore.release` if it would increase the value above the initial value. + + Bounded semapthores support the :ref:`context management + protocol `. + + This class is :ref:`not thread safe `. + + +.. _async-with-locks: + +Using locks, conditions and semaphores in the :keyword:`async with` statement +----------------------------------------------------------------------------- + +:class:`Lock`, :class:`Condition`, :class:`Semaphore`, and +:class:`BoundedSemaphore` objects can be used in :keyword:`async with` +statements. + +The :meth:`acquire` method will be called when the block is entered, +and :meth:`release` will be called when the block is exited. Hence, +the following snippet:: + + async with lock: + # do something... + +is equivalent to:: + + await lock.acquire() + try: + # do something... + finally: + lock.release() + +.. deprecated:: 3.7 + + Lock acquiring using ``await lock`` or ``yield from lock`` and + :keyword:`with` statement (``with await lock``, ``with (yield from + lock)``) are deprecated. diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index aa6ed3eaea6..57eb69e7cf0 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -3,6 +3,7 @@ __all__ = ['Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore'] import collections +import warnings from . import events from . import futures @@ -63,6 +64,9 @@ def __iter__(self): # # finally: # lock.release() + warnings.warn("'with (yield from lock)' is deprecated " + "use 'async with lock' instead", + DeprecationWarning, stacklevel=2) yield from self.acquire() return _ContextManager(self) @@ -71,6 +75,9 @@ def __iter__(self): return _ContextManager(self) def __await__(self): + warnings.warn("'with await lock' is deprecated " + "use 'async with lock' instead", + DeprecationWarning, stacklevel=2) # To make "with await lock" work. return self.__acquire_ctx().__await__() diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index c1f8d6e3673..f365a45106e 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -42,7 +42,8 @@ def test_repr(self): @asyncio.coroutine def acquire_lock(): - yield from lock + with self.assertWarns(DeprecationWarning): + yield from lock self.loop.run_until_complete(acquire_lock()) self.assertTrue(repr(lock).endswith('[locked]>')) @@ -53,7 +54,8 @@ def test_lock(self): @asyncio.coroutine def acquire_lock(): - return (yield from lock) + with self.assertWarns(DeprecationWarning): + return (yield from lock) res = self.loop.run_until_complete(acquire_lock()) @@ -63,6 +65,32 @@ def acquire_lock(): lock.release() self.assertFalse(lock.locked()) + def test_lock_by_with_statement(self): + loop = asyncio.new_event_loop() # don't use TestLoop quirks + self.set_event_loop(loop) + primitives = [ + asyncio.Lock(loop=loop), + asyncio.Condition(loop=loop), + asyncio.Semaphore(loop=loop), + asyncio.BoundedSemaphore(loop=loop), + ] + + @asyncio.coroutine + def test(lock): + yield from asyncio.sleep(0.01, loop=loop) + self.assertFalse(lock.locked()) + with self.assertWarns(DeprecationWarning): + with (yield from lock) as _lock: + self.assertIs(_lock, None) + self.assertTrue(lock.locked()) + yield from asyncio.sleep(0.01, loop=loop) + self.assertTrue(lock.locked()) + self.assertFalse(lock.locked()) + + for primitive in primitives: + loop.run_until_complete(test(primitive)) + self.assertFalse(primitive.locked()) + def test_acquire(self): lock = asyncio.Lock(loop=self.loop) result = [] @@ -212,7 +240,8 @@ def test_context_manager(self): @asyncio.coroutine def acquire_lock(): - return (yield from lock) + with self.assertWarns(DeprecationWarning): + return (yield from lock) with self.loop.run_until_complete(acquire_lock()): self.assertTrue(lock.locked()) @@ -224,7 +253,8 @@ def test_context_manager_cant_reuse(self): @asyncio.coroutine def acquire_lock(): - return (yield from lock) + with self.assertWarns(DeprecationWarning): + return (yield from lock) # This spells "yield from lock" outside a generator. cm = self.loop.run_until_complete(acquire_lock()) @@ -668,7 +698,8 @@ def test_context_manager(self): @asyncio.coroutine def acquire_cond(): - return (yield from cond) + with self.assertWarns(DeprecationWarning): + return (yield from cond) with self.loop.run_until_complete(acquire_cond()): self.assertTrue(cond.locked()) @@ -751,7 +782,8 @@ def test_semaphore(self): @asyncio.coroutine def acquire_lock(): - return (yield from sem) + with self.assertWarns(DeprecationWarning): + return (yield from sem) res = self.loop.run_until_complete(acquire_lock()) @@ -893,7 +925,8 @@ def test_context_manager(self): @asyncio.coroutine def acquire_lock(): - return (yield from sem) + with self.assertWarns(DeprecationWarning): + return (yield from sem) with self.loop.run_until_complete(acquire_lock()): self.assertFalse(sem.locked()) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py index 77eb7cd6455..442577017d9 100644 --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -59,12 +59,13 @@ def test_context_manager_with_await(self): 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()) + with self.assertWarns(DeprecationWarning): + 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)) diff --git a/Misc/NEWS.d/next/Library/2017-12-09-11-30-35.bpo-32253.TQHSYF.rst b/Misc/NEWS.d/next/Library/2017-12-09-11-30-35.bpo-32253.TQHSYF.rst new file mode 100644 index 00000000000..2916410e457 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-09-11-30-35.bpo-32253.TQHSYF.rst @@ -0,0 +1,2 @@ +Deprecate ``yield from lock``, ``await lock``, ``with (yield from lock)`` +and ``with await lock`` for asyncio synchronization primitives. From webhook-mailer at python.org Sat Dec 9 13:26:56 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 09 Dec 2017 18:26:56 -0000 Subject: [Python-checkins] closes bpo-31650: PEP 552 (Deterministic pycs) implementation (#4575) Message-ID: https://github.com/python/cpython/commit/42aa93b8ff2f7879282b06efc73a31ec7785e602 commit: 42aa93b8ff2f7879282b06efc73a31ec7785e602 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-09T10:26:52-08:00 summary: closes bpo-31650: PEP 552 (Deterministic pycs) implementation (#4575) Python now supports checking bytecode cache up-to-dateness with a hash of the source contents rather than volatile source metadata. See the PEP for details. While a fairly straightforward idea, quite a lot of code had to be modified due to the pervasiveness of pyc implementation details in the codebase. Changes in this commit include: - The core changes to importlib to understand how to read, validate, and regenerate hash-based pycs. - Support for generating hash-based pycs in py_compile and compileall. - Modifications to our siphash implementation to support passing a custom key. We then expose it to importlib through _imp. - Updates to all places in the interpreter, standard library, and tests that manually generate or parse pyc files to grok the new format. - Support in the interpreter command line code for long options like --check-hash-based-pycs. - Tests and documentation for all of the above. files: A Include/internal/hash.h A Include/internal/import.h A Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-38-44.bpo-31650.JWf_Im.rst M Doc/glossary.rst M Doc/library/compileall.rst M Doc/library/importlib.rst M Doc/library/py_compile.rst M Doc/reference/import.rst M Doc/using/cmdline.rst M Doc/whatsnew/3.7.rst M Include/pygetopt.h M Lib/compileall.py M Lib/importlib/_bootstrap_external.py M Lib/importlib/util.py M Lib/modulefinder.py M Lib/pkgutil.py M Lib/py_compile.py M Lib/test/test_compileall.py M Lib/test/test_imp.py M Lib/test/test_import/__init__.py M Lib/test/test_importlib/source/test_file_loader.py M Lib/test/test_importlib/test_abc.py M Lib/test/test_py_compile.py M Lib/test/test_zipimport.py M Misc/python.man M Modules/main.c M Modules/zipimport.c M Python/clinic/import.c.h M Python/getopt.c M Python/import.c M Python/importlib_external.h M Python/pyhash.c M Python/pythonrun.c diff --git a/Doc/glossary.rst b/Doc/glossary.rst index ba4d300c0e9..e875e1fc8a0 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -458,6 +458,12 @@ Glossary is believed that overcoming this performance issue would make the implementation much more complicated and therefore costlier to maintain. + + hash-based pyc + A bytecode cache file that uses the the hash rather than the last-modified + time of the corresponding source file to determine its validity. See + :ref:`pyc-invalidation`. + hashable An object is *hashable* if it has a hash value which never changes during its lifetime (it needs a :meth:`__hash__` method), and can be compared to diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst index c1af02b0d82..7b3963da894 100644 --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -83,6 +83,16 @@ compile Python sources. If ``0`` is used, then the result of :func:`os.cpu_count()` will be used. +.. cmdoption:: --invalidation-mode [timestamp|checked-hash|unchecked-hash] + + Control how the generated pycs will be invalidated at runtime. The default + setting, ``timestamp``, means that ``.pyc`` files with the source timestamp + and size embedded will be generated. The ``checked-hash`` and + ``unchecked-hash`` values cause hash-based pycs to be generated. Hash-based + pycs embed a hash of the source file contents rather than a timestamp. See + :ref:`pyc-invalidation` for more information on how Python validates bytecode + cache files at runtime. + .. versionchanged:: 3.2 Added the ``-i``, ``-b`` and ``-h`` options. @@ -91,6 +101,9 @@ compile Python sources. was changed to a multilevel value. ``-b`` will always produce a byte-code file ending in ``.pyc``, never ``.pyo``. +.. versionchanged:: 3.7 + Added the ``--invalidation-mode`` parameter. + There is no command-line option to control the optimization level used by the :func:`compile` function, because the Python interpreter itself already @@ -99,7 +112,7 @@ provides the option: :program:`python -O -m compileall`. Public functions ---------------- -.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1) +.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) Recursively descend the directory tree named by *dir*, compiling all :file:`.py` files along the way. Return a true value if all the files compiled successfully, @@ -140,6 +153,10 @@ Public functions then sequential compilation will be used as a fallback. If *workers* is lower than ``0``, a :exc:`ValueError` will be raised. + *invalidation_mode* should be a member of the + :class:`py_compile.PycInvalidationMode` enum and controls how the generated + pycs are invalidated at runtime. + .. versionchanged:: 3.2 Added the *legacy* and *optimize* parameter. @@ -156,7 +173,10 @@ Public functions .. versionchanged:: 3.6 Accepts a :term:`path-like object`. -.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1) + .. versionchanged:: 3.7 + The *invalidation_mode* parameter was added. + +.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) Compile the file with path *fullname*. Return a true value if the file compiled successfully, and a false value otherwise. @@ -184,6 +204,10 @@ Public functions *optimize* specifies the optimization level for the compiler. It is passed to the built-in :func:`compile` function. + *invalidation_mode* should be a member of the + :class:`py_compile.PycInvalidationMode` enum and controls how the generated + pycs are invalidated at runtime. + .. versionadded:: 3.2 .. versionchanged:: 3.5 @@ -193,7 +217,10 @@ Public functions The *legacy* parameter only writes out ``.pyc`` files, not ``.pyo`` files no matter what the value of *optimize* is. -.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1) + .. versionchanged:: 3.7 + The *invalidation_mode* parameter was added. + +.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) Byte-compile all the :file:`.py` files found along ``sys.path``. Return a true value if all the files compiled successfully, and a false value otherwise. @@ -213,6 +240,9 @@ Public functions The *legacy* parameter only writes out ``.pyc`` files, not ``.pyo`` files no matter what the value of *optimize* is. + .. versionchanged:: 3.7 + The *invalidation_mode* parameter was added. + To force a recompile of all the :file:`.py` files in the :file:`Lib/` subdirectory and all its subdirectories:: diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 3d350e8d0d5..3cafb41d447 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -67,6 +67,9 @@ generically as an :term:`importer`) to participate in the import process. :pep:`489` Multi-phase extension module initialization + :pep:`552` + Deterministic pycs + :pep:`3120` Using UTF-8 as the Default Source Encoding @@ -1327,6 +1330,14 @@ an :term:`importer`. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. +.. function:: source_hash(source_bytes) + + Return the hash of *source_bytes* as bytes. A hash-based ``.pyc`` file embeds + the :func:`source_hash` of the corresponding source file's contents in its + header. + + .. versionadded:: 3.7 + .. class:: LazyLoader(loader) A class which postpones the execution of the loader of a module until the diff --git a/Doc/library/py_compile.rst b/Doc/library/py_compile.rst index 0af8fb15b36..a4f06de597b 100644 --- a/Doc/library/py_compile.rst +++ b/Doc/library/py_compile.rst @@ -27,7 +27,7 @@ byte-code cache files in the directory containing the source code. Exception raised when an error occurs while attempting to compile the file. -.. function:: compile(file, cfile=None, dfile=None, doraise=False, optimize=-1) +.. function:: compile(file, cfile=None, dfile=None, doraise=False, optimize=-1, invalidation_mode=PycInvalidationMode.TIMESTAMP) Compile a source file to byte-code and write out the byte-code cache file. The source code is loaded from the file named *file*. The byte-code is @@ -53,6 +53,10 @@ byte-code cache files in the directory containing the source code. :func:`compile` function. The default of ``-1`` selects the optimization level of the current interpreter. + *invalidation_mode* should be a member of the :class:`PycInvalidationMode` + enum and controls how the generated ``.pyc`` files are invalidated at + runtime. + .. versionchanged:: 3.2 Changed default value of *cfile* to be :PEP:`3147`-compliant. Previous default was *file* + ``'c'`` (``'o'`` if optimization was enabled). @@ -65,6 +69,41 @@ byte-code cache files in the directory containing the source code. caveat that :exc:`FileExistsError` is raised if *cfile* is a symlink or non-regular file. + .. versionchanged:: 3.7 + The *invalidation_mode* parameter was added as specified in :pep:`552`. + + +.. class:: PycInvalidationMode + + A enumeration of possible methods the interpreter can use to determine + whether a bytecode file is up to date with a source file. The ``.pyc`` file + indicates the desired invalidation mode in its header. See + :ref:`pyc-invalidation` for more information on how Python invalidates + ``.pyc`` files at runtime. + + .. versionadded:: 3.7 + + .. attribute:: TIMESTAMP + + The ``.pyc`` file includes the timestamp and size of the source file, + which Python will compare against the metadata of the source file at + runtime to determine if the ``.pyc`` file needs to be regenerated. + + .. attribute:: CHECKED_HASH + + The ``.pyc`` file includes a hash of the source file content, which Python + will compare against the source at runtime to determine if the ``.pyc`` + file needs to be regenerated. + + .. attribute:: UNCHECKED_HASH + + Like :attr:`CHECKED_HASH`, the ``.pyc`` file includes a hash of the source + file content. However, Python will at runtime assume the ``.pyc`` file is + up to date and not validate the ``.pyc`` against the source file at all. + + This option is useful when the ``.pycs`` are kept up to date by some + system external to Python like a build system. + .. function:: main(args=None) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 881e0aed32e..45d417295d0 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -675,6 +675,33 @@ Here are the exact rules used: :meth:`~importlib.abc.Loader.module_repr` method, if defined, before trying either approach described above. However, the method is deprecated. +.. _pyc-invalidation: + +Cached bytecode invalidation +---------------------------- + +Before Python loads cached bytecode from ``.pyc`` file, it checks whether the +cache is up-to-date with the source ``.py`` file. By default, Python does this +by storing the source's last-modified timestamp and size in the cache file when +writing it. At runtime, the import system then validates the cache file by +checking the stored metadata in the cache file against at source's +metadata. + +Python also supports "hash-based" cache files, which store a hash of the source +file's contents rather than its metadata. There are two variants of hash-based +``.pyc`` files: checked and unchecked. For checked hash-based ``.pyc`` files, +Python validates the cache file by hashing the source file and comparing the +resulting hash with the hash in the cache file. If a checked hash-based cache +file is found to be invalid, Python regenerates it and writes a new checked +hash-based cache file. For unchecked hash-based ``.pyc`` files, Python simply +assumes the cache file is valid if it exists. Hash-based ``.pyc`` files +validation behavior may be overridden with the :option:`--check-hash-based-pycs` +flag. + +.. versionchanged:: 3.7 + Added hash-based ``.pyc`` files. Previously, Python only supported + timestamp-based invalidation of bytecode caches. + The Path Based Finder ===================== diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index d110ae3baf2..716bc821b4a 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -210,6 +210,20 @@ Miscellaneous options import of source modules. See also :envvar:`PYTHONDONTWRITEBYTECODE`. +.. cmdoption:: --check-hash-based-pycs default|always|never + + Control the validation behavior of hash-based ``.pyc`` files. See + :ref:`pyc-invalidation`. When set to ``default``, checked and unchecked + hash-based bytecode cache files are validated according to their default + semantics. When set to ``always``, all hash-based ``.pyc`` files, whether + checked or unchecked, are validated against their corresponding source + file. When set to ``never``, hash-based ``.pyc`` files are not validated + against their corresponding source files. + + The semantics of timestamp-based ``.pyc`` files are unaffected by this + option. + + .. cmdoption:: -d Turn on parser debugging output (for expert only, depending on compilation diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 9363730bf1f..34876626597 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -197,6 +197,33 @@ variable is not set in practice. See :option:`-X` ``dev`` for the details. +Hash-based pycs +--------------- + +Python has traditionally checked the up-to-dateness of bytecode cache files +(i.e., ``.pyc`` files) by comparing the source metadata (last-modified timestamp +and size) with source metadata saved in the cache file header when it was +generated. While effective, this invalidation method has its drawbacks. When +filesystem timestamps are too coarse, Python can miss source updates, leading to +user confusion. Additionally, having a timestamp in the cache file is +problematic for `build reproduciblity `_ and +content-based build systems. + +:pep:`552` extends the pyc format to allow the hash of the source file to be +used for invalidation instead of the source timestamp. Such ``.pyc`` files are +called "hash-based". By default, Python still uses timestamp-based invalidation +and does not generate hash-based ``.pyc`` files at runtime. Hash-based ``.pyc`` +files may be generated with :mod:`py_compile` or :mod:`compileall`. + +Hash-based ``.pyc`` files come in two variants: checked and unchecked. Python +validates checked hash-based ``.pyc`` files against the corresponding source +files at runtime but doesn't do so for unchecked hash-based pycs. Unchecked +hash-based ``.pyc`` files are a useful performance optimization for environments +where a system external to Python (e.g., the build system) is responsible for +keeping ``.pyc`` files up-to-date. + +See :ref:`pyc-invalidation` for more information. + Other Language Changes ====================== diff --git a/Include/internal/hash.h b/Include/internal/hash.h new file mode 100644 index 00000000000..e14b80a7f27 --- /dev/null +++ b/Include/internal/hash.h @@ -0,0 +1,6 @@ +#ifndef Py_INTERNAL_HASH_H +#define Py_INTERNAL_HASH_H + +uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t); + +#endif diff --git a/Include/internal/import.h b/Include/internal/import.h new file mode 100644 index 00000000000..4746e755755 --- /dev/null +++ b/Include/internal/import.h @@ -0,0 +1,6 @@ +#ifndef Py_INTERNAL_IMPORT_H +#define Py_INTERNAL_IMPORT_H + +extern const char *_Py_CheckHashBasedPycsMode; + +#endif diff --git a/Include/pygetopt.h b/Include/pygetopt.h index 962720c876c..3e3fe364901 100644 --- a/Include/pygetopt.h +++ b/Include/pygetopt.h @@ -12,7 +12,14 @@ PyAPI_DATA(wchar_t *) _PyOS_optarg; PyAPI_FUNC(void) _PyOS_ResetGetOpt(void); -PyAPI_FUNC(int) _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring); +typedef struct { + const wchar_t *name; + int has_arg; + int val; +} _PyOS_LongOption; + +PyAPI_FUNC(int) _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring, + const _PyOS_LongOption *longopts, int *longindex); #endif /* !Py_LIMITED_API */ #ifdef __cplusplus diff --git a/Lib/compileall.py b/Lib/compileall.py index 1c9ceb69309..72592126d74 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -52,7 +52,8 @@ def _walk_dir(dir, ddir=None, maxlevels=10, quiet=0): maxlevels=maxlevels - 1, quiet=quiet) def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, - quiet=0, legacy=False, optimize=-1, workers=1): + quiet=0, legacy=False, optimize=-1, workers=1, + invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP): """Byte-compile all modules in the given directory tree. Arguments (only dir is required): @@ -67,6 +68,7 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, legacy: if True, produce legacy pyc paths instead of PEP 3147 paths optimize: optimization level or -1 for level of the interpreter workers: maximum number of parallel workers + invalidation_mode: how the up-to-dateness of the pyc will be checked """ if workers is not None and workers < 0: raise ValueError('workers must be greater or equal to 0') @@ -81,18 +83,20 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, ddir=ddir, force=force, rx=rx, quiet=quiet, legacy=legacy, - optimize=optimize), + optimize=optimize, + invalidation_mode=invalidation_mode), files) success = min(results, default=True) else: for file in files: if not compile_file(file, ddir, force, rx, quiet, - legacy, optimize): + legacy, optimize, invalidation_mode): success = False return success def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, - legacy=False, optimize=-1): + legacy=False, optimize=-1, + invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP): """Byte-compile one file. Arguments (only fullname is required): @@ -105,6 +109,7 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, no output with 2 legacy: if True, produce legacy pyc paths instead of PEP 3147 paths optimize: optimization level or -1 for level of the interpreter + invalidation_mode: how the up-to-dateness of the pyc will be checked """ success = True if quiet < 2 and isinstance(fullname, os.PathLike): @@ -134,10 +139,10 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, if not force: try: mtime = int(os.stat(fullname).st_mtime) - expect = struct.pack('<4sl', importlib.util.MAGIC_NUMBER, - mtime) + expect = struct.pack('<4sll', importlib.util.MAGIC_NUMBER, + 0, mtime) with open(cfile, 'rb') as chandle: - actual = chandle.read(8) + actual = chandle.read(12) if expect == actual: return success except OSError: @@ -146,7 +151,8 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, print('Compiling {!r}...'.format(fullname)) try: ok = py_compile.compile(fullname, cfile, dfile, True, - optimize=optimize) + optimize=optimize, + invalidation_mode=invalidation_mode) except py_compile.PyCompileError as err: success = False if quiet >= 2: @@ -175,7 +181,8 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, return success def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=0, - legacy=False, optimize=-1): + legacy=False, optimize=-1, + invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP): """Byte-compile all module on sys.path. Arguments (all optional): @@ -186,6 +193,7 @@ def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=0, quiet: as for compile_dir() (default 0) legacy: as for compile_dir() (default False) optimize: as for compile_dir() (default -1) + invalidation_mode: as for compiler_dir() """ success = True for dir in sys.path: @@ -193,9 +201,16 @@ def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=0, if quiet < 2: print('Skipping current directory') else: - success = success and compile_dir(dir, maxlevels, None, - force, quiet=quiet, - legacy=legacy, optimize=optimize) + success = success and compile_dir( + dir, + maxlevels, + None, + force, + quiet=quiet, + legacy=legacy, + optimize=optimize, + invalidation_mode=invalidation_mode, + ) return success @@ -238,6 +253,11 @@ def main(): 'to the equivalent of -l sys.path')) parser.add_argument('-j', '--workers', default=1, type=int, help='Run compileall concurrently') + invalidation_modes = [mode.name.lower().replace('_', '-') + for mode in py_compile.PycInvalidationMode] + parser.add_argument('--invalidation-mode', default='timestamp', + choices=sorted(invalidation_modes), + help='How the pycs will be invalidated at runtime') args = parser.parse_args() compile_dests = args.compile_dest @@ -266,23 +286,29 @@ def main(): if args.workers is not None: args.workers = args.workers or None + ivl_mode = args.invalidation_mode.replace('-', '_').upper() + invalidation_mode = py_compile.PycInvalidationMode[ivl_mode] + success = True try: if compile_dests: for dest in compile_dests: if os.path.isfile(dest): if not compile_file(dest, args.ddir, args.force, args.rx, - args.quiet, args.legacy): + args.quiet, args.legacy, + invalidation_mode=invalidation_mode): success = False else: if not compile_dir(dest, maxlevels, args.ddir, args.force, args.rx, args.quiet, - args.legacy, workers=args.workers): + args.legacy, workers=args.workers, + invalidation_mode=invalidation_mode): success = False return success else: return compile_path(legacy=args.legacy, force=args.force, - quiet=args.quiet) + quiet=args.quiet, + invalidation_mode=invalidation_mode) except KeyboardInterrupt: if args.quiet < 2: print("\n[interrupted]") diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 41de8a7b863..e808507d3bb 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -242,6 +242,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.6rc1 3379 (more thorough __class__ validation #23722) # Python 3.7a0 3390 (add LOAD_METHOD and CALL_METHOD opcodes) # Python 3.7a0 3391 (update GET_AITER #31709) +# Python 3.7a0 3392 (PEP 552: Deterministic pycs) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -250,7 +251,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3391).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3392).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' @@ -429,63 +430,93 @@ def _find_module_shim(self, fullname): return loader -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(). +def _classify_pyc(data, name, exc_details): + """Perform basic validity checking of a pyc header and return the flags field, + which determines how the pyc should be further validated against the source. - All other arguments are used to enhance error reporting. + *data* is the contents of the pyc file. (Only the first 16 bytes are + required, though.) - 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. + *name* is the name of the module being imported. It is used for logging. + + *exc_details* is a dictionary passed to ImportError if it raised for + improved debugging. + + ImportError is raised when the magic number is incorrect or when the flags + field is invalid. 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) + message = f'bad magic number in {name!r}: {magic!r}' _bootstrap._verbose_message('{}', message) raise ImportError(message, **exc_details) - elif len(raw_timestamp) != 4: - message = 'reached EOF while reading timestamp in {!r}'.format(name) + if len(data) < 16: + message = f'reached EOF while reading pyc header of {name!r}' _bootstrap._verbose_message('{}', message) raise EOFError(message) - elif len(raw_size) != 4: - message = 'reached EOF while reading size of source in {!r}'.format(name) + flags = _r_long(data[4:8]) + # Only the first two flags are defined. + if flags & ~0b11: + message = f'invalid flags {flags!r} in {name!r}' + raise ImportError(message, **exc_details) + return flags + + +def _validate_timestamp_pyc(data, source_mtime, source_size, name, + exc_details): + """Validate a pyc against the source last-modified time. + + *data* is the contents of the pyc file. (Only the first 16 bytes are + required.) + + *source_mtime* is the last modified timestamp of the source file. + + *source_size* is None or the size of the source file in bytes. + + *name* is the name of the module being imported. It is used for logging. + + *exc_details* is a dictionary passed to ImportError if it raised for + improved debugging. + + An ImportError is raised if the bytecode is stale. + + """ + if _r_long(data[8:12]) != (source_mtime & 0xFFFFFFFF): + message = f'bytecode is stale for {name!r}' _bootstrap._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) - _bootstrap._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:] + raise ImportError(message, **exc_details) + if (source_size is not None and + _r_long(data[12:16]) != (source_size & 0xFFFFFFFF)): + raise ImportError(f'bytecode is stale for {name!r}', **exc_details) + + +def _validate_hash_pyc(data, source_hash, name, exc_details): + """Validate a hash-based pyc by checking the real source hash against the one in + the pyc header. + + *data* is the contents of the pyc file. (Only the first 16 bytes are + required.) + + *source_hash* is the importlib.util.source_hash() of the source file. + + *name* is the name of the module being imported. It is used for logging. + + *exc_details* is a dictionary passed to ImportError if it raised for + improved debugging. + + An ImportError is raised if the bytecode is stale. + + """ + if data[8:16] != source_hash: + raise ImportError( + f'hash in bytecode doesn\'t match hash of source {name!r}', + **exc_details, + ) def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None): - """Compile bytecode as returned by _validate_bytecode_header().""" + """Compile bytecode as found in a pyc.""" code = marshal.loads(data) if isinstance(code, _code_type): _bootstrap._verbose_message('code object from {!r}', bytecode_path) @@ -496,16 +527,28 @@ def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None): 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.""" + +def _code_to_timestamp_pyc(code, mtime=0, source_size=0): + "Produce the data for a timestamp-based pyc." data = bytearray(MAGIC_NUMBER) + data.extend(_w_long(0)) data.extend(_w_long(mtime)) data.extend(_w_long(source_size)) data.extend(marshal.dumps(code)) return data +def _code_to_hash_pyc(code, source_hash, checked=True): + "Produce the data for a hash-based pyc." + data = bytearray(MAGIC_NUMBER) + flags = 0b1 | checked << 1 + data.extend(_w_long(flags)) + assert len(source_hash) == 8 + data.extend(source_hash) + data.extend(marshal.dumps(code)) + return data + + def decode_source(source_bytes): """Decode bytes representing source code and return the string. @@ -751,6 +794,10 @@ def get_code(self, fullname): """ source_path = self.get_filename(fullname) source_mtime = None + source_bytes = None + source_hash = None + hash_based = False + check_source = True try: bytecode_path = cache_from_source(source_path) except NotImplementedError: @@ -767,10 +814,34 @@ def get_code(self, fullname): except OSError: pass else: + exc_details = { + 'name': fullname, + 'path': bytecode_path, + } try: - bytes_data = _validate_bytecode_header(data, - source_stats=st, name=fullname, - path=bytecode_path) + flags = _classify_pyc(data, fullname, exc_details) + bytes_data = memoryview(data)[16:] + hash_based = flags & 0b1 != 0 + if hash_based: + check_source = flags & 0b10 != 0 + if (_imp.check_hash_based_pycs != 'never' and + (check_source or + _imp.check_hash_based_pycs == 'always')): + source_bytes = self.get_data(source_path) + source_hash = _imp.source_hash( + _RAW_MAGIC_NUMBER, + source_bytes, + ) + _validate_hash_pyc(data, source_hash, fullname, + exc_details) + else: + _validate_timestamp_pyc( + data, + source_mtime, + st['size'], + fullname, + exc_details, + ) except (ImportError, EOFError): pass else: @@ -779,13 +850,19 @@ def get_code(self, fullname): return _compile_bytecode(bytes_data, name=fullname, bytecode_path=bytecode_path, source_path=source_path) - source_bytes = self.get_data(source_path) + if source_bytes is None: + source_bytes = self.get_data(source_path) code_object = self.source_to_code(source_bytes, source_path) _bootstrap._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)) + if hash_based: + if source_hash is None: + source_hash = _imp.source_hash(source_bytes) + data = _code_to_hash_pyc(code_object, source_hash, check_source) + else: + data = _code_to_timestamp_pyc(code_object, source_mtime, + len(source_bytes)) try: self._cache_bytecode(source_path, bytecode_path, data) _bootstrap._verbose_message('wrote {!r}', bytecode_path) @@ -887,8 +964,18 @@ class SourcelessFileLoader(FileLoader, _LoaderBasics): 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) + # Call _classify_pyc to do basic validation of the pyc but ignore the + # result. There's no source to check against. + exc_details = { + 'name': fullname, + 'path': path, + } + _classify_pyc(data, fullname, exc_details) + return _compile_bytecode( + memoryview(data)[16:], + name=fullname, + bytecode_path=path, + ) def get_source(self, fullname): """Return None as there is no source code.""" diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py index 41c74d4cc6c..9d0a90d2973 100644 --- a/Lib/importlib/util.py +++ b/Lib/importlib/util.py @@ -5,18 +5,25 @@ from ._bootstrap import spec_from_loader from ._bootstrap import _find_spec from ._bootstrap_external import MAGIC_NUMBER +from ._bootstrap_external import _RAW_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 _imp import functools import sys import types import warnings +def source_hash(source_bytes): + "Return the hash of *source_bytes* as used in hash-based pyc files." + return _imp.source_hash(_RAW_MAGIC_NUMBER, source_bytes) + + def resolve_name(name, package): """Resolve a relative module name to an absolute one.""" if not name.startswith('.'): diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py index e277ca72f8e..10320a74d94 100644 --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -287,11 +287,12 @@ def load_module(self, fqname, fp, pathname, file_info): co = compile(fp.read()+'\n', pathname, 'exec') elif type == imp.PY_COMPILED: try: - marshal_data = importlib._bootstrap_external._validate_bytecode_header(fp.read()) + data = fp.read() + importlib._bootstrap_external._classify_pyc(data, fqname, {}) except ImportError as exc: self.msgout(2, "raise ImportError: " + str(exc), pathname) raise - co = marshal.loads(marshal_data) + co = marshal.loads(memoryview(data)[16:]) else: co = None m = self.add_module(fqname) diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index 9180eaed84d..8474a773e7c 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -46,7 +46,7 @@ def read_code(stream): if magic != importlib.util.MAGIC_NUMBER: return None - stream.read(8) # Skip timestamp and size + stream.read(12) # Skip rest of the header return marshal.load(stream) diff --git a/Lib/py_compile.py b/Lib/py_compile.py index 11c5b505cc6..a0f4defdce6 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -3,6 +3,7 @@ This module has intimate knowledge of the format of .pyc files. """ +import enum import importlib._bootstrap_external import importlib.machinery import importlib.util @@ -11,7 +12,7 @@ import sys import traceback -__all__ = ["compile", "main", "PyCompileError"] +__all__ = ["compile", "main", "PyCompileError", "PycInvalidationMode"] class PyCompileError(Exception): @@ -62,7 +63,14 @@ def __str__(self): return self.msg -def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1): +class PycInvalidationMode(enum.Enum): + TIMESTAMP = 1 + CHECKED_HASH = 2 + UNCHECKED_HASH = 3 + + +def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1, + invalidation_mode=PycInvalidationMode.TIMESTAMP): """Byte-compile one Python source file to Python bytecode. :param file: The source file name. @@ -79,6 +87,7 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1): :param optimize: The optimization level for the compiler. Valid values are -1, 0, 1 and 2. A value of -1 means to use the optimization level of the current interpreter, as given by -O command line options. + :param invalidation_mode: :return: Path to the resulting byte compiled file. @@ -136,9 +145,17 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1): os.makedirs(dirname) except FileExistsError: pass - source_stats = loader.path_stats(file) - bytecode = importlib._bootstrap_external._code_to_bytecode( + if invalidation_mode == PycInvalidationMode.TIMESTAMP: + source_stats = loader.path_stats(file) + bytecode = importlib._bootstrap_external._code_to_timestamp_pyc( code, source_stats['mtime'], source_stats['size']) + else: + source_hash = importlib.util.source_hash(source_bytes) + bytecode = importlib._bootstrap_external._code_to_hash_pyc( + code, + source_hash, + (invalidation_mode == PycInvalidationMode.CHECKED_HASH), + ) mode = importlib._bootstrap_external._calc_mode(file) importlib._bootstrap_external._write_atomic(cfile, bytecode, mode) return cfile diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 2356efcaec7..38d7b996c7c 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -48,9 +48,9 @@ def add_bad_source_file(self): def data(self): with open(self.bc_path, 'rb') as file: - data = file.read(8) + data = file.read(12) mtime = int(os.stat(self.source_path).st_mtime) - compare = struct.pack('<4sl', importlib.util.MAGIC_NUMBER, mtime) + compare = struct.pack('<4sll', importlib.util.MAGIC_NUMBER, 0, mtime) return data, compare @unittest.skipUnless(hasattr(os, 'stat'), 'test needs os.stat()') @@ -70,8 +70,8 @@ def recreation_check(self, metadata): def test_mtime(self): # Test a change in mtime leads to a new .pyc. - self.recreation_check(struct.pack('<4sl', importlib.util.MAGIC_NUMBER, - 1)) + self.recreation_check(struct.pack('<4sll', importlib.util.MAGIC_NUMBER, + 0, 1)) def test_magic_number(self): # Test a change in mtime leads to a new .pyc. @@ -519,6 +519,19 @@ def test_invalid_arg_produces_message(self): out = self.assertRunOK('badfilename') self.assertRegex(out, b"Can't list 'badfilename'") + def test_pyc_invalidation_mode(self): + script_helper.make_script(self.pkgdir, 'f1', '') + pyc = importlib.util.cache_from_source( + os.path.join(self.pkgdir, 'f1.py')) + self.assertRunOK('--invalidation-mode=checked-hash', self.pkgdir) + with open(pyc, 'rb') as fp: + data = fp.read() + self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b11) + self.assertRunOK('--invalidation-mode=unchecked-hash', self.pkgdir) + with open(pyc, 'rb') as fp: + data = fp.read() + self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b01) + @skipUnless(_have_multiprocessing, "requires multiprocessing") def test_workers(self): bar2fn = script_helper.make_script(self.directory, 'bar2', '') diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py index b70ec7caddb..a115e60d4e4 100644 --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -4,11 +4,13 @@ import os.path import sys from test import support +from test.support import script_helper import unittest import warnings with warnings.catch_warnings(): warnings.simplefilter('ignore', DeprecationWarning) import imp +import _imp def requires_load_dynamic(meth): @@ -329,6 +331,25 @@ class BadSpec: with self.assertRaises(TypeError): create_dynamic(BadSpec()) + def test_source_hash(self): + self.assertEqual(_imp.source_hash(42, b'hi'), b'\xc6\xe7Z\r\x03:}\xab') + self.assertEqual(_imp.source_hash(43, b'hi'), b'\x85\x9765\xf8\x9a\x8b9') + + def test_pyc_invalidation_mode_from_cmdline(self): + cases = [ + ([], "default"), + (["--check-hash-based-pycs", "default"], "default"), + (["--check-hash-based-pycs", "always"], "always"), + (["--check-hash-based-pycs", "never"], "never"), + ] + for interp_args, expected in cases: + args = interp_args + [ + "-c", + "import _imp; print(_imp.check_hash_based_pycs)", + ] + res = script_helper.assert_python_ok(*args) + self.assertEqual(res.out.strip().decode('utf-8'), expected) + class ReloadTests(unittest.TestCase): diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 5a610ba3126..ceea79f6ad9 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -598,7 +598,7 @@ def test_module_without_source(self): def test_foreign_code(self): py_compile.compile(self.file_name) with open(self.compiled_name, "rb") as f: - header = f.read(12) + header = f.read(16) code = marshal.load(f) constants = list(code.co_consts) foreign_code = importlib.import_module.__code__ diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py index a151149f31a..643a02c9ad6 100644 --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -235,6 +235,123 @@ def test_unloadable(self): warnings.simplefilter('ignore', DeprecationWarning) loader.load_module('bad name') + @util.writes_bytecode_files + def test_checked_hash_based_pyc(self): + with util.create_modules('_temp') as mapping: + source = mapping['_temp'] + pyc = self.util.cache_from_source(source) + with open(source, 'wb') as fp: + fp.write(b'state = "old"') + os.utime(source, (50, 50)) + py_compile.compile( + source, + invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH, + ) + loader = self.machinery.SourceFileLoader('_temp', source) + mod = types.ModuleType('_temp') + mod.__spec__ = self.util.spec_from_loader('_temp', loader) + loader.exec_module(mod) + self.assertEqual(mod.state, 'old') + # Write a new source with the same mtime and size as before. + with open(source, 'wb') as fp: + fp.write(b'state = "new"') + os.utime(source, (50, 50)) + loader.exec_module(mod) + self.assertEqual(mod.state, 'new') + with open(pyc, 'rb') as fp: + data = fp.read() + self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b11) + self.assertEqual( + self.util.source_hash(b'state = "new"'), + data[8:16], + ) + + @util.writes_bytecode_files + def test_overriden_checked_hash_based_pyc(self): + with util.create_modules('_temp') as mapping, \ + unittest.mock.patch('_imp.check_hash_based_pycs', 'never'): + source = mapping['_temp'] + pyc = self.util.cache_from_source(source) + with open(source, 'wb') as fp: + fp.write(b'state = "old"') + os.utime(source, (50, 50)) + py_compile.compile( + source, + invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH, + ) + loader = self.machinery.SourceFileLoader('_temp', source) + mod = types.ModuleType('_temp') + mod.__spec__ = self.util.spec_from_loader('_temp', loader) + loader.exec_module(mod) + self.assertEqual(mod.state, 'old') + # Write a new source with the same mtime and size as before. + with open(source, 'wb') as fp: + fp.write(b'state = "new"') + os.utime(source, (50, 50)) + loader.exec_module(mod) + self.assertEqual(mod.state, 'old') + + @util.writes_bytecode_files + def test_unchecked_hash_based_pyc(self): + with util.create_modules('_temp') as mapping: + source = mapping['_temp'] + pyc = self.util.cache_from_source(source) + with open(source, 'wb') as fp: + fp.write(b'state = "old"') + os.utime(source, (50, 50)) + py_compile.compile( + source, + invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH, + ) + loader = self.machinery.SourceFileLoader('_temp', source) + mod = types.ModuleType('_temp') + mod.__spec__ = self.util.spec_from_loader('_temp', loader) + loader.exec_module(mod) + self.assertEqual(mod.state, 'old') + # Update the source file, which should be ignored. + with open(source, 'wb') as fp: + fp.write(b'state = "new"') + loader.exec_module(mod) + self.assertEqual(mod.state, 'old') + with open(pyc, 'rb') as fp: + data = fp.read() + self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b1) + self.assertEqual( + self.util.source_hash(b'state = "old"'), + data[8:16], + ) + + @util.writes_bytecode_files + def test_overiden_unchecked_hash_based_pyc(self): + with util.create_modules('_temp') as mapping, \ + unittest.mock.patch('_imp.check_hash_based_pycs', 'always'): + source = mapping['_temp'] + pyc = self.util.cache_from_source(source) + with open(source, 'wb') as fp: + fp.write(b'state = "old"') + os.utime(source, (50, 50)) + py_compile.compile( + source, + invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH, + ) + loader = self.machinery.SourceFileLoader('_temp', source) + mod = types.ModuleType('_temp') + mod.__spec__ = self.util.spec_from_loader('_temp', loader) + loader.exec_module(mod) + self.assertEqual(mod.state, 'old') + # Update the source file, which should be ignored. + with open(source, 'wb') as fp: + fp.write(b'state = "new"') + loader.exec_module(mod) + self.assertEqual(mod.state, 'new') + with open(pyc, 'rb') as fp: + data = fp.read() + self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b1) + self.assertEqual( + self.util.source_hash(b'state = "new"'), + data[8:16], + ) + (Frozen_SimpleTest, Source_SimpleTest @@ -247,15 +364,17 @@ class BadBytecodeTest: def import_(self, file, module_name): raise NotImplementedError - def manipulate_bytecode(self, name, mapping, manipulator, *, - del_source=False): + def manipulate_bytecode(self, + name, mapping, manipulator, *, + del_source=False, + invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP): """Manipulate the bytecode of a module by passing it into a callable that returns what to use as the new bytecode.""" try: del sys.modules['_temp'] except KeyError: pass - py_compile.compile(mapping[name]) + py_compile.compile(mapping[name], invalidation_mode=invalidation_mode) if not del_source: bytecode_path = self.util.cache_from_source(mapping[name]) else: @@ -294,24 +413,51 @@ def _test_magic_only(self, test, *, del_source=False): del_source=del_source) test('_temp', mapping, bc_path) + def _test_partial_flags(self, test, *, del_source=False): + with util.create_modules('_temp') as mapping: + bc_path = self.manipulate_bytecode('_temp', mapping, + lambda bc: bc[:7], + del_source=del_source) + test('_temp', mapping, bc_path) + + def _test_partial_hash(self, test, *, del_source=False): + with util.create_modules('_temp') as mapping: + bc_path = self.manipulate_bytecode( + '_temp', + mapping, + lambda bc: bc[:13], + del_source=del_source, + invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH, + ) + test('_temp', mapping, bc_path) + with util.create_modules('_temp') as mapping: + bc_path = self.manipulate_bytecode( + '_temp', + mapping, + lambda bc: bc[:13], + del_source=del_source, + invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH, + ) + test('_temp', mapping, bc_path) + def _test_partial_timestamp(self, test, *, del_source=False): with util.create_modules('_temp') as mapping: bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:7], + lambda bc: bc[:11], del_source=del_source) test('_temp', mapping, bc_path) def _test_partial_size(self, test, *, del_source=False): with util.create_modules('_temp') as mapping: bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:11], + lambda bc: bc[:15], del_source=del_source) test('_temp', mapping, bc_path) def _test_no_marshal(self, *, del_source=False): with util.create_modules('_temp') as mapping: bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:12], + lambda bc: bc[:16], del_source=del_source) file_path = mapping['_temp'] if not del_source else bc_path with self.assertRaises(EOFError): @@ -320,7 +466,7 @@ def _test_no_marshal(self, *, del_source=False): def _test_non_code_marshal(self, *, del_source=False): with util.create_modules('_temp') as mapping: bytecode_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:12] + marshal.dumps(b'abcd'), + lambda bc: bc[:16] + marshal.dumps(b'abcd'), del_source=del_source) file_path = mapping['_temp'] if not del_source else bytecode_path with self.assertRaises(ImportError) as cm: @@ -331,7 +477,7 @@ def _test_non_code_marshal(self, *, del_source=False): def _test_bad_marshal(self, *, del_source=False): with util.create_modules('_temp') as mapping: bytecode_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:12] + b'', + lambda bc: bc[:16] + b'', del_source=del_source) file_path = mapping['_temp'] if not del_source else bytecode_path with self.assertRaises(EOFError): @@ -376,7 +522,7 @@ def test_empty_file(self): def test(name, mapping, bytecode_path): self.import_(mapping[name], name) with open(bytecode_path, 'rb') as file: - self.assertGreater(len(file.read()), 12) + self.assertGreater(len(file.read()), 16) self._test_empty_file(test) @@ -384,7 +530,7 @@ def test_partial_magic(self): def test(name, mapping, bytecode_path): self.import_(mapping[name], name) with open(bytecode_path, 'rb') as file: - self.assertGreater(len(file.read()), 12) + self.assertGreater(len(file.read()), 16) self._test_partial_magic(test) @@ -395,7 +541,7 @@ def test_magic_only(self): def test(name, mapping, bytecode_path): self.import_(mapping[name], name) with open(bytecode_path, 'rb') as file: - self.assertGreater(len(file.read()), 12) + self.assertGreater(len(file.read()), 16) self._test_magic_only(test) @@ -418,10 +564,30 @@ def test_partial_timestamp(self): def test(name, mapping, bc_path): self.import_(mapping[name], name) with open(bc_path, 'rb') as file: - self.assertGreater(len(file.read()), 12) + self.assertGreater(len(file.read()), 16) self._test_partial_timestamp(test) + @util.writes_bytecode_files + def test_partial_flags(self): + # When the flags is partial, regenerate the .pyc, else raise EOFError. + def test(name, mapping, bc_path): + self.import_(mapping[name], name) + with open(bc_path, 'rb') as file: + self.assertGreater(len(file.read()), 16) + + self._test_partial_flags(test) + + @util.writes_bytecode_files + def test_partial_hash(self): + # When the hash is partial, regenerate the .pyc, else raise EOFError. + def test(name, mapping, bc_path): + self.import_(mapping[name], name) + with open(bc_path, 'rb') as file: + self.assertGreater(len(file.read()), 16) + + self._test_partial_hash(test) + @util.writes_bytecode_files def test_partial_size(self): # When the size is partial, regenerate the .pyc, else @@ -429,7 +595,7 @@ def test_partial_size(self): def test(name, mapping, bc_path): self.import_(mapping[name], name) with open(bc_path, 'rb') as file: - self.assertGreater(len(file.read()), 12) + self.assertGreater(len(file.read()), 16) self._test_partial_size(test) @@ -459,13 +625,13 @@ def test_old_timestamp(self): py_compile.compile(mapping['_temp']) bytecode_path = self.util.cache_from_source(mapping['_temp']) with open(bytecode_path, 'r+b') as bytecode_file: - bytecode_file.seek(4) + bytecode_file.seek(8) bytecode_file.write(zeros) self.import_(mapping['_temp'], '_temp') source_mtime = os.path.getmtime(mapping['_temp']) source_timestamp = self.importlib._w_long(source_mtime) with open(bytecode_path, 'rb') as bytecode_file: - bytecode_file.seek(4) + bytecode_file.seek(8) self.assertEqual(bytecode_file.read(4), source_timestamp) # [bytecode read-only] @@ -560,6 +726,20 @@ def test(name, mapping, bytecode_path): self._test_partial_timestamp(test, del_source=True) + def test_partial_flags(self): + def test(name, mapping, bytecode_path): + with self.assertRaises(EOFError): + self.import_(bytecode_path, name) + + self._test_partial_flags(test, del_source=True) + + def test_partial_hash(self): + def test(name, mapping, bytecode_path): + with self.assertRaises(EOFError): + self.import_(bytecode_path, name) + + self._test_partial_hash(test, del_source=True) + def test_partial_size(self): def test(name, mapping, bytecode_path): with self.assertRaises(EOFError): diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py index 54b2da6a3d2..4ba28c6638b 100644 --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -673,6 +673,7 @@ def __init__(self, path, magic=None): if magic is None: magic = self.util.MAGIC_NUMBER data = bytearray(magic) + data.extend(self.init._w_long(0)) data.extend(self.init._w_long(self.source_mtime)) data.extend(self.init._w_long(self.source_size)) code_object = compile(self.source, self.path, 'exec', @@ -836,6 +837,7 @@ def verify_code(self, code_object, *, bytecode_written=False): if bytecode_written: self.assertIn(self.cached, self.loader.written) data = bytearray(self.util.MAGIC_NUMBER) + data.extend(self.init._w_long(0)) data.extend(self.init._w_long(self.loader.source_mtime)) data.extend(self.init._w_long(self.loader.source_size)) data.extend(marshal.dumps(code_object)) diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index 4a6caa57187..bcb686c86b5 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -122,6 +122,24 @@ def test_optimization_path(self): # Specifying optimized bytecode should lead to a path reflecting that. self.assertIn('opt-2', py_compile.compile(self.source_path, optimize=2)) + def test_invalidation_mode(self): + py_compile.compile( + self.source_path, + invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH, + ) + with open(self.cache_path, 'rb') as fp: + flags = importlib._bootstrap_external._classify_pyc( + fp.read(), 'test', {}) + self.assertEqual(flags, 0b11) + py_compile.compile( + self.source_path, + invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH, + ) + with open(self.cache_path, 'rb') as fp: + flags = importlib._bootstrap_external._classify_pyc( + fp.read(), 'test', {}) + self.assertEqual(flags, 0b1) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 67ca39b8066..901bebdd71d 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -40,7 +40,7 @@ def make_pyc(co, mtime, size): else: mtime = int(-0x100000000 + int(mtime)) pyc = (importlib.util.MAGIC_NUMBER + - struct.pack(" @@ -61,6 +62,11 @@ static int orig_argc; #define PROGRAM_OPTS BASE_OPTS +static const _PyOS_LongOption longoptions[] = { + {L"check-hash-based-pycs", 1, 0}, + {NULL, 0, 0}, +}; + /* Short usage message (with %s for argv0) */ static const char usage_line[] = "usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n"; @@ -98,6 +104,8 @@ static const char usage_3[] = "\ also PYTHONWARNINGS=arg\n\ -x : skip first line of source, allowing use of non-Unix forms of #!cmd\n\ -X opt : set implementation-specific option\n\ +--check-hash-based-pycs always|default|never:\n\ + control how Python invalidates hash-based .pyc files\n\ "; static const char usage_4[] = "\ file : program read from script file\n\ @@ -393,6 +401,7 @@ typedef struct { int quiet_flag; /* Py_QuietFlag, -q */ int skip_first_line; /* -x option */ _Py_OptList xoptions; /* -X options */ + const char *check_hash_pycs_mode; /* --check-hash-based-pycs */ #ifdef MS_WINDOWS int legacy_windows_fs_encoding; /* Py_LegacyWindowsFSEncodingFlag, PYTHONLEGACYWINDOWSFSENCODING */ @@ -577,7 +586,9 @@ pymain_parse_cmdline_impl(_PyMain *pymain) _PyOS_ResetGetOpt(); do { - int c = _PyOS_GetOpt(pymain->argc, pymain->argv, PROGRAM_OPTS); + int longindex = -1; + int c = _PyOS_GetOpt(pymain->argc, pymain->argv, PROGRAM_OPTS, + longoptions, &longindex); if (c == EOF) { break; } @@ -608,6 +619,22 @@ pymain_parse_cmdline_impl(_PyMain *pymain) } switch (c) { + case 0: + // Handle long option. + assert(longindex == 0); // Only one long option now. + if (!wcscmp(_PyOS_optarg, L"always")) { + cmdline->check_hash_pycs_mode = "always"; + } else if (!wcscmp(_PyOS_optarg, L"never")) { + cmdline->check_hash_pycs_mode = "never"; + } else if (!wcscmp(_PyOS_optarg, L"default")) { + cmdline->check_hash_pycs_mode = "default"; + } else { + fprintf(stderr, "--check-hash-based-pycs must be one of " + "'default', 'always', or 'never'\n"); + return 1; + } + break; + case 'b': cmdline->bytes_warning++; break; @@ -1085,6 +1112,8 @@ pymain_set_global_config(_PyMain *pymain) pymain_set_flag(&Py_UnbufferedStdioFlag, cmdline->use_unbuffered_io); pymain_set_flag(&Py_VerboseFlag, cmdline->verbosity); pymain_set_flag(&Py_QuietFlag, cmdline->quiet_flag); + if (cmdline->check_hash_pycs_mode) + _Py_CheckHashBasedPycsMode = cmdline->check_hash_pycs_mode; #ifdef MS_WINDOWS pymain_set_flag(&Py_LegacyWindowsFSEncodingFlag, cmdline->legacy_windows_fs_encoding); pymain_set_flag(&Py_LegacyWindowsStdioFlag, cmdline->legacy_windows_stdio); diff --git a/Modules/zipimport.c b/Modules/zipimport.c index 009480bac58..1d0e0ba9137 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "internal/import.h" #include "internal/pystate.h" #include "structmember.h" #include "osdefs.h" @@ -1305,7 +1306,7 @@ unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime) unsigned char *buf = (unsigned char *)PyBytes_AsString(data); Py_ssize_t size = PyBytes_Size(data); - if (size < 12) { + if (size < 16) { PyErr_SetString(ZipImportError, "bad pyc data"); return NULL; @@ -1319,7 +1320,16 @@ unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime) Py_RETURN_NONE; /* signal caller to try alternative */ } - if (mtime != 0 && !eq_mtime(get_uint32(buf + 4), mtime)) { + uint32_t flags = get_uint32(buf + 4); + if (flags != 0) { + // Hash-based pyc. We currently refuse to handle checked hash-based + // pycs. We could validate hash-based pycs against the source, but it + // seems likely that most people putting hash-based pycs in a zipfile + // will use unchecked ones. + if (strcmp(_Py_CheckHashBasedPycsMode, "never") && + (flags != 0x1 || !strcmp(_Py_CheckHashBasedPycsMode, "always"))) + Py_RETURN_NONE; + } else if ((mtime != 0 && !eq_mtime(get_uint32(buf + 8), mtime))) { if (Py_VerboseFlag) { PySys_FormatStderr("# %R has bad mtime\n", pathname); @@ -1329,7 +1339,7 @@ unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime) /* XXX the pyc's size field is ignored; timestamp collisions are probably unimportant with zip files. */ - code = PyMarshal_ReadObjectFromString((char *)buf + 12, size - 12); + code = PyMarshal_ReadObjectFromString((char *)buf + 16, size - 16); if (code == NULL) { return NULL; } diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h index ddd694ff9be..1955e504550 100644 --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -354,6 +354,41 @@ _imp_exec_builtin(PyObject *module, PyObject *mod) return return_value; } +PyDoc_STRVAR(_imp_source_hash__doc__, +"source_hash($module, /, key, source)\n" +"--\n" +"\n"); + +#define _IMP_SOURCE_HASH_METHODDEF \ + {"source_hash", (PyCFunction)_imp_source_hash, METH_FASTCALL|METH_KEYWORDS, _imp_source_hash__doc__}, + +static PyObject * +_imp_source_hash_impl(PyObject *module, long key, Py_buffer *source); + +static PyObject * +_imp_source_hash(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"key", "source", NULL}; + static _PyArg_Parser _parser = {"ly*:source_hash", _keywords, 0}; + long key; + Py_buffer source = {NULL, NULL}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &key, &source)) { + goto exit; + } + return_value = _imp_source_hash_impl(module, key, &source); + +exit: + /* Cleanup for source */ + if (source.obj) { + PyBuffer_Release(&source); + } + + return return_value; +} + #ifndef _IMP_CREATE_DYNAMIC_METHODDEF #define _IMP_CREATE_DYNAMIC_METHODDEF #endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */ @@ -361,4 +396,4 @@ _imp_exec_builtin(PyObject *module, PyObject *mod) #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=d068dd493e513604 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e8b2c0b0d0a75da8 input=a9049054013a1b77]*/ diff --git a/Python/getopt.c b/Python/getopt.c index 5cf4cbd7bb3..de32ad4d8cb 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -51,7 +51,8 @@ void _PyOS_ResetGetOpt(void) opt_ptr = L""; } -int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring) +int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring, + const _PyOS_LongOption *longopts, int *longindex) { wchar_t *ptr; wchar_t option; @@ -86,13 +87,41 @@ int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring) return 'V'; } - opt_ptr = &argv[_PyOS_optind++][1]; } if ((option = *opt_ptr++) == L'\0') return -1; + if (option == L'-') { + // Parse long option. + if (*opt_ptr == L'\0') { + fprintf(stderr, "expected long option\n"); + return -1; + } + *longindex = 0; + const _PyOS_LongOption *opt; + for (opt = &longopts[*longindex]; opt->name; opt = &longopts[++(*longindex)]) { + if (!wcscmp(opt->name, opt_ptr)) + break; + } + if (!opt->name) { + fprintf(stderr, "unknown option %ls\n", argv[_PyOS_optind - 1]); + return '_'; + } + opt_ptr = L""; + if (!opt->has_arg) { + return opt->val; + } + if (_PyOS_optind >= argc) { + fprintf(stderr, "Argument expected for the %ls options\n", + argv[_PyOS_optind - 1]); + return '_'; + } + _PyOS_optarg = argv[_PyOS_optind++]; + return opt->val; + } + if (option == 'J') { if (_PyOS_opterr) fprintf(stderr, "-J is reserved for Jython\n"); diff --git a/Python/import.c b/Python/import.c index dc79685abd4..b2d751111bf 100644 --- a/Python/import.c +++ b/Python/import.c @@ -5,6 +5,8 @@ #include "Python-ast.h" #undef Yield /* undefine macro conflicting with winbase.h */ +#include "internal/hash.h" +#include "internal/import.h" #include "internal/pystate.h" #include "errcode.h" #include "marshal.h" @@ -2184,6 +2186,34 @@ _imp_exec_builtin_impl(PyObject *module, PyObject *mod) return exec_builtin_or_dynamic(mod); } +/*[clinic input] +_imp.source_hash + + key: long + source: Py_buffer +[clinic start generated code]*/ + +static PyObject * +_imp_source_hash_impl(PyObject *module, long key, Py_buffer *source) +/*[clinic end generated code: output=edb292448cf399ea input=9aaad1e590089789]*/ +{ + uint64_t hash = _Py_KeyedHash((uint64_t)key, source->buf, source->len); +#if !PY_LITTLE_ENDIAN + // Force to little-endian. There really ought to be a succinct standard way + // to do this. + union { + uint64_t x; + unsigned char data[sizeof(uint64_t)]; + } pun; + pun.x = hash; + for (size_t i = 0; i < sizeof(pun.data); i++) { + pun.data[sizeof(pun.data) - i - 1] = pun.data[i]; + } + hash = pun.x; +#endif + return PyBytes_FromStringAndSize((const char *)&hash, sizeof(hash)); +} + PyDoc_STRVAR(doc_imp, "(Extremely) low-level import machinery bits as used by importlib and imp."); @@ -2203,6 +2233,7 @@ static PyMethodDef imp_methods[] = { _IMP_EXEC_DYNAMIC_METHODDEF _IMP_EXEC_BUILTIN_METHODDEF _IMP__FIX_CO_FILENAME_METHODDEF + _IMP_SOURCE_HASH_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2219,6 +2250,8 @@ static struct PyModuleDef impmodule = { NULL }; +const char *_Py_CheckHashBasedPycsMode = "default"; + PyMODINIT_FUNC PyInit_imp(void) { @@ -2230,6 +2263,15 @@ PyInit_imp(void) d = PyModule_GetDict(m); if (d == NULL) goto failure; + PyObject *pyc_mode = PyUnicode_FromString(_Py_CheckHashBasedPycsMode); + if (pyc_mode == NULL) { + goto failure; + } + if (PyDict_SetItemString(d, "check_hash_based_pycs", pyc_mode) < 0) { + Py_DECREF(pyc_mode); + goto failure; + } + Py_DECREF(pyc_mode); return m; failure: diff --git a/Python/importlib_external.h b/Python/importlib_external.h index f122f14f542..907392c209d 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1,1266 +1,1659 @@ /* 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,5,0,0, - 0,64,0,0,0,115,248,1,0,0,100,0,90,0,100,91, - 90,1,100,92,90,2,101,2,101,1,23,0,90,3,100,4, + 0,64,0,0,0,115,16,2,0,0,100,0,90,0,100,98, + 90,1,100,99,90,2,101,2,101,1,23,0,90,3,100,4, 100,5,132,0,90,4,100,6,100,7,132,0,90,5,100,8, 100,9,132,0,90,6,100,10,100,11,132,0,90,7,100,12, 100,13,132,0,90,8,100,14,100,15,132,0,90,9,100,16, 100,17,132,0,90,10,100,18,100,19,132,0,90,11,100,20, - 100,21,132,0,90,12,100,93,100,23,100,24,132,1,90,13, + 100,21,132,0,90,12,100,100,100,23,100,24,132,1,90,13, 101,14,101,13,106,15,131,1,90,16,100,25,160,17,100,26, 100,27,161,2,100,28,23,0,90,18,101,19,160,20,101,18, 100,27,161,2,90,21,100,29,90,22,100,30,90,23,100,31, 103,1,90,24,100,32,103,1,90,25,101,25,4,0,90,26, - 90,27,100,94,100,33,100,34,156,1,100,35,100,36,132,3, + 90,27,100,101,100,33,100,34,156,1,100,35,100,36,132,3, 90,28,100,37,100,38,132,0,90,29,100,39,100,40,132,0, 90,30,100,41,100,42,132,0,90,31,100,43,100,44,132,0, 90,32,100,45,100,46,132,0,90,33,100,47,100,48,132,0, - 90,34,100,95,100,49,100,50,132,1,90,35,100,96,100,51, - 100,52,132,1,90,36,100,97,100,54,100,55,132,1,90,37, - 100,56,100,57,132,0,90,38,101,39,131,0,90,40,100,98, - 100,33,101,40,100,58,156,2,100,59,100,60,132,3,90,41, - 71,0,100,61,100,62,132,0,100,62,131,2,90,42,71,0, - 100,63,100,64,132,0,100,64,131,2,90,43,71,0,100,65, - 100,66,132,0,100,66,101,43,131,3,90,44,71,0,100,67, - 100,68,132,0,100,68,131,2,90,45,71,0,100,69,100,70, - 132,0,100,70,101,45,101,44,131,4,90,46,71,0,100,71, - 100,72,132,0,100,72,101,45,101,43,131,4,90,47,103,0, - 90,48,71,0,100,73,100,74,132,0,100,74,101,45,101,43, - 131,4,90,49,71,0,100,75,100,76,132,0,100,76,131,2, - 90,50,71,0,100,77,100,78,132,0,100,78,131,2,90,51, - 71,0,100,79,100,80,132,0,100,80,131,2,90,52,71,0, - 100,81,100,82,132,0,100,82,131,2,90,53,100,99,100,83, - 100,84,132,1,90,54,100,85,100,86,132,0,90,55,100,87, - 100,88,132,0,90,56,100,89,100,90,132,0,90,57,100,33, - 83,0,41,100,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,3,0,0,0,3,0,0, - 0,115,60,0,0,0,116,0,106,1,160,2,116,3,161,1, - 114,48,116,0,106,1,160,2,116,4,161,1,114,30,100,1, - 137,0,110,4,100,2,137,0,135,0,102,1,100,3,100,4, - 132,8,125,0,110,8,100,5,100,4,132,0,125,0,124,0, - 83,0,41,6,78,90,12,80,89,84,72,79,78,67,65,83, - 69,79,75,115,12,0,0,0,80,89,84,72,79,78,67,65, - 83,69,79,75,99,0,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,19,0,0,0,115,10,0,0,0,136,0, - 116,0,106,1,107,6,83,0,41,1,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,41,2,218,3,95,111,115,90,7,101,110,118,105,114,111, - 110,169,0,41,1,218,3,107,101,121,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,37,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,83,0,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,6,0,0,0,114,7,0,0,0,41,0,0,0, - 115,2,0,0,0,0,2,41,5,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,218,35,95,67,65,83,69,95,73,78,83,69,78,83,73, - 84,73,86,69,95,80,76,65,84,70,79,82,77,83,95,83, - 84,82,95,75,69,89,41,1,114,7,0,0,0,114,4,0, - 0,0,41,1,114,5,0,0,0,114,6,0,0,0,218,16, - 95,109,97,107,101,95,114,101,108,97,120,95,99,97,115,101, - 30,0,0,0,115,14,0,0,0,0,1,12,1,12,1,6, - 2,4,2,14,4,8,3,114,13,0,0,0,99,1,0,0, - 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, - 0,115,20,0,0,0,116,0,124,0,131,1,100,1,64,0, - 160,1,100,2,100,3,161,2,83,0,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,6,0,0,0,218,7,95,119,95,108,111,110,103,47,0, - 0,0,115,2,0,0,0,0,2,114,19,0,0,0,99,1, - 0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,67, - 0,0,0,115,12,0,0,0,116,0,160,1,124,0,100,1, - 161,2,83,0,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,15,0,0,0,41,2,114,16, - 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,6,0,0,0,218,7,95,114,95, - 108,111,110,103,52,0,0,0,115,2,0,0,0,0,2,114, - 21,0,0,0,99,0,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,71,0,0,0,115,20,0,0,0,116,0, - 160,1,100,1,100,2,132,0,124,0,68,0,131,1,161,1, - 83,0,41,3,122,31,82,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,5,0,0,0,83,0,0,0,115,26,0,0,0,103, - 0,124,0,93,18,125,1,124,1,114,4,124,1,160,0,116, - 1,161,1,145,2,113,4,83,0,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, - 6,0,0,0,250,10,60,108,105,115,116,99,111,109,112,62, - 59,0,0,0,115,2,0,0,0,6,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,6,0,0,0,218,10,95,112,97,116, - 104,95,106,111,105,110,57,0,0,0,115,4,0,0,0,0, - 2,10,1,114,30,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,96,0, - 0,0,116,0,116,1,131,1,100,1,107,2,114,36,124,0, - 160,2,116,3,161,1,92,3,125,1,125,2,125,3,124,1, - 124,3,102,2,83,0,120,50,116,4,124,0,131,1,68,0, - 93,38,125,4,124,4,116,1,107,6,114,46,124,0,106,5, - 124,4,100,1,100,2,141,2,92,2,125,1,125,3,124,1, - 124,3,102,2,83,0,113,46,87,0,100,3,124,0,102,2, - 83,0,41,4,122,32,82,101,112,108,97,99,101,109,101,110, - 116,32,102,111,114,32,111,115,46,112,97,116,104,46,115,112, - 108,105,116,40,41,46,233,1,0,0,0,41,1,90,8,109, - 97,120,115,112,108,105,116,218,0,41,6,218,3,108,101,110, - 114,23,0,0,0,218,10,114,112,97,114,116,105,116,105,111, - 110,114,27,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,18,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,11,95,112,97,116,104,95,115,112,108,105, - 116,63,0,0,0,115,16,0,0,0,0,2,12,1,16,1, - 8,1,14,1,8,1,18,1,12,1,114,40,0,0,0,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,10,0,0,0,116,0,160,1,124,0,161, - 1,83,0,41,1,122,126,83,116,97,116,32,116,104,101,32, - 112,97,116,104,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,37,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,218,10,95,112,97,116,104,95, - 115,116,97,116,75,0,0,0,115,2,0,0,0,0,7,114, - 41,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,48,0,0,0,121,12, - 116,0,124,0,131,1,125,2,87,0,110,20,4,0,116,1, - 107,10,114,32,1,0,1,0,1,0,100,1,83,0,88,0, - 124,2,106,2,100,2,64,0,124,1,107,2,83,0,41,3, - 122,49,84,101,115,116,32,119,104,101,116,104,101,114,32,116, - 104,101,32,112,97,116,104,32,105,115,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,32,109,111,100,101,32,116,121, - 112,101,46,70,105,0,240,0,0,41,3,114,41,0,0,0, - 218,7,79,83,69,114,114,111,114,218,7,115,116,95,109,111, - 100,101,41,3,114,37,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,6,0,0,0,218,18,95,112,97,116,104, - 95,105,115,95,109,111,100,101,95,116,121,112,101,85,0,0, - 0,115,10,0,0,0,0,2,2,1,12,1,14,1,6,1, - 114,45,0,0,0,99,1,0,0,0,0,0,0,0,1,0, - 0,0,3,0,0,0,67,0,0,0,115,10,0,0,0,116, - 0,124,0,100,1,131,2,83,0,41,2,122,31,82,101,112, - 108,97,99,101,109,101,110,116,32,102,111,114,32,111,115,46, - 112,97,116,104,46,105,115,102,105,108,101,46,105,0,128,0, - 0,41,1,114,45,0,0,0,41,1,114,37,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,12, - 95,112,97,116,104,95,105,115,102,105,108,101,94,0,0,0, - 115,2,0,0,0,0,2,114,46,0,0,0,99,1,0,0, - 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, - 0,115,22,0,0,0,124,0,115,12,116,0,160,1,161,0, - 125,0,116,2,124,0,100,1,131,2,83,0,41,2,122,30, - 82,101,112,108,97,99,101,109,101,110,116,32,102,111,114,32, - 111,115,46,112,97,116,104,46,105,115,100,105,114,46,105,0, - 64,0,0,41,3,114,3,0,0,0,218,6,103,101,116,99, - 119,100,114,45,0,0,0,41,1,114,37,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,218,11,95, - 112,97,116,104,95,105,115,100,105,114,99,0,0,0,115,6, - 0,0,0,0,2,4,1,8,1,114,48,0,0,0,233,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,162,0,0,0,100,1,160, - 0,124,0,116,1,124,0,131,1,161,2,125,3,116,2,160, - 3,124,3,116,2,106,4,116,2,106,5,66,0,116,2,106, - 6,66,0,124,2,100,2,64,0,161,3,125,4,121,50,116, - 7,160,8,124,4,100,3,161,2,143,16,125,5,124,5,160, - 9,124,1,161,1,1,0,87,0,100,4,81,0,82,0,88, - 0,116,2,160,10,124,3,124,0,161,2,1,0,87,0,110, - 58,4,0,116,11,107,10,114,156,1,0,1,0,1,0,121, - 14,116,2,160,12,124,3,161,1,1,0,87,0,110,20,4, - 0,116,11,107,10,114,148,1,0,1,0,1,0,89,0,110, - 2,88,0,130,0,89,0,110,2,88,0,100,4,83,0,41, - 5,122,162,66,101,115,116,45,101,102,102,111,114,116,32,102, - 117,110,99,116,105,111,110,32,116,111,32,119,114,105,116,101, - 32,100,97,116,97,32,116,111,32,97,32,112,97,116,104,32, - 97,116,111,109,105,99,97,108,108,121,46,10,32,32,32,32, - 66,101,32,112,114,101,112,97,114,101,100,32,116,111,32,104, - 97,110,100,108,101,32,97,32,70,105,108,101,69,120,105,115, - 116,115,69,114,114,111,114,32,105,102,32,99,111,110,99,117, - 114,114,101,110,116,32,119,114,105,116,105,110,103,32,111,102, - 32,116,104,101,10,32,32,32,32,116,101,109,112,111,114,97, - 114,121,32,102,105,108,101,32,105,115,32,97,116,116,101,109, - 112,116,101,100,46,122,5,123,125,46,123,125,105,182,1,0, - 0,90,2,119,98,78,41,13,218,6,102,111,114,109,97,116, - 218,2,105,100,114,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,42,0,0,0,90,6,117,110, - 108,105,110,107,41,6,114,37,0,0,0,218,4,100,97,116, - 97,114,44,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,6,0,0,0,218,13,95,119,114,105,116, - 101,95,97,116,111,109,105,99,106,0,0,0,115,26,0,0, - 0,0,5,16,1,6,1,26,1,2,3,14,1,20,1,16, - 1,14,1,2,1,14,1,14,1,6,1,114,58,0,0,0, - 105,63,13,0,0,233,2,0,0,0,114,15,0,0,0,115, - 2,0,0,0,13,10,90,11,95,95,112,121,99,97,99,104, - 101,95,95,122,4,111,112,116,45,122,3,46,112,121,122,4, - 46,112,121,99,78,41,1,218,12,111,112,116,105,109,105,122, - 97,116,105,111,110,99,2,0,0,0,1,0,0,0,11,0, - 0,0,6,0,0,0,67,0,0,0,115,244,0,0,0,124, - 1,100,1,107,9,114,52,116,0,160,1,100,2,116,2,161, - 2,1,0,124,2,100,1,107,9,114,40,100,3,125,3,116, - 3,124,3,131,1,130,1,124,1,114,48,100,4,110,2,100, - 5,125,2,116,4,160,5,124,0,161,1,125,0,116,6,124, - 0,131,1,92,2,125,4,125,5,124,5,160,7,100,6,161, - 1,92,3,125,6,125,7,125,8,116,8,106,9,106,10,125, - 9,124,9,100,1,107,8,114,114,116,11,100,7,131,1,130, - 1,100,4,160,12,124,6,114,126,124,6,110,2,124,8,124, - 7,124,9,103,3,161,1,125,10,124,2,100,1,107,8,114, - 172,116,8,106,13,106,14,100,8,107,2,114,164,100,4,125, - 2,110,8,116,8,106,13,106,14,125,2,116,15,124,2,131, - 1,125,2,124,2,100,4,107,3,114,224,124,2,160,16,161, - 0,115,210,116,17,100,9,160,18,124,2,161,1,131,1,130, - 1,100,10,160,18,124,10,116,19,124,2,161,3,125,10,116, - 20,124,4,116,21,124,10,116,22,100,8,25,0,23,0,131, - 3,83,0,41,11,97,254,2,0,0,71,105,118,101,110,32, - 116,104,101,32,112,97,116,104,32,116,111,32,97,32,46,112, - 121,32,102,105,108,101,44,32,114,101,116,117,114,110,32,116, - 104,101,32,112,97,116,104,32,116,111,32,105,116,115,32,46, - 112,121,99,32,102,105,108,101,46,10,10,32,32,32,32,84, - 104,101,32,46,112,121,32,102,105,108,101,32,100,111,101,115, - 32,110,111,116,32,110,101,101,100,32,116,111,32,101,120,105, - 115,116,59,32,116,104,105,115,32,115,105,109,112,108,121,32, - 114,101,116,117,114,110,115,32,116,104,101,32,112,97,116,104, - 32,116,111,32,116,104,101,10,32,32,32,32,46,112,121,99, - 32,102,105,108,101,32,99,97,108,99,117,108,97,116,101,100, - 32,97,115,32,105,102,32,116,104,101,32,46,112,121,32,102, - 105,108,101,32,119,101,114,101,32,105,109,112,111,114,116,101, - 100,46,10,10,32,32,32,32,84,104,101,32,39,111,112,116, - 105,109,105,122,97,116,105,111,110,39,32,112,97,114,97,109, - 101,116,101,114,32,99,111,110,116,114,111,108,115,32,116,104, - 101,32,112,114,101,115,117,109,101,100,32,111,112,116,105,109, - 105,122,97,116,105,111,110,32,108,101,118,101,108,32,111,102, - 10,32,32,32,32,116,104,101,32,98,121,116,101,99,111,100, - 101,32,102,105,108,101,46,32,73,102,32,39,111,112,116,105, - 109,105,122,97,116,105,111,110,39,32,105,115,32,110,111,116, - 32,78,111,110,101,44,32,116,104,101,32,115,116,114,105,110, - 103,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110, - 10,32,32,32,32,111,102,32,116,104,101,32,97,114,103,117, - 109,101,110,116,32,105,115,32,116,97,107,101,110,32,97,110, - 100,32,118,101,114,105,102,105,101,100,32,116,111,32,98,101, - 32,97,108,112,104,97,110,117,109,101,114,105,99,32,40,101, - 108,115,101,32,86,97,108,117,101,69,114,114,111,114,10,32, - 32,32,32,105,115,32,114,97,105,115,101,100,41,46,10,10, - 32,32,32,32,84,104,101,32,100,101,98,117,103,95,111,118, - 101,114,114,105,100,101,32,112,97,114,97,109,101,116,101,114, - 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, - 73,102,32,100,101,98,117,103,95,111,118,101,114,114,105,100, - 101,32,105,115,32,110,111,116,32,78,111,110,101,44,10,32, - 32,32,32,97,32,84,114,117,101,32,118,97,108,117,101,32, - 105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,115, - 101,116,116,105,110,103,32,39,111,112,116,105,109,105,122,97, - 116,105,111,110,39,32,116,111,32,116,104,101,32,101,109,112, - 116,121,32,115,116,114,105,110,103,10,32,32,32,32,119,104, - 105,108,101,32,97,32,70,97,108,115,101,32,118,97,108,117, - 101,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32, - 116,111,32,115,101,116,116,105,110,103,32,39,111,112,116,105, - 109,105,122,97,116,105,111,110,39,32,116,111,32,39,49,39, - 46,10,10,32,32,32,32,73,102,32,115,121,115,46,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,46,99,97,99, - 104,101,95,116,97,103,32,105,115,32,78,111,110,101,32,116, - 104,101,110,32,78,111,116,73,109,112,108,101,109,101,110,116, - 101,100,69,114,114,111,114,32,105,115,32,114,97,105,115,101, - 100,46,10,10,32,32,32,32,78,122,70,116,104,101,32,100, - 101,98,117,103,95,111,118,101,114,114,105,100,101,32,112,97, - 114,97,109,101,116,101,114,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,59,32,117,115,101,32,39,111,112,116,105, - 109,105,122,97,116,105,111,110,39,32,105,110,115,116,101,97, - 100,122,50,100,101,98,117,103,95,111,118,101,114,114,105,100, - 101,32,111,114,32,111,112,116,105,109,105,122,97,116,105,111, - 110,32,109,117,115,116,32,98,101,32,115,101,116,32,116,111, - 32,78,111,110,101,114,32,0,0,0,114,31,0,0,0,218, - 1,46,122,36,115,121,115,46,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,46,99,97,99,104,101,95,116,97,103, - 32,105,115,32,78,111,110,101,233,0,0,0,0,122,24,123, - 33,114,125,32,105,115,32,110,111,116,32,97,108,112,104,97, - 110,117,109,101,114,105,99,122,7,123,125,46,123,125,123,125, - 41,23,218,9,95,119,97,114,110,105,110,103,115,218,4,119, - 97,114,110,218,18,68,101,112,114,101,99,97,116,105,111,110, - 87,97,114,110,105,110,103,218,9,84,121,112,101,69,114,114, - 111,114,114,3,0,0,0,218,6,102,115,112,97,116,104,114, - 40,0,0,0,114,34,0,0,0,114,8,0,0,0,218,14, - 105,109,112,108,101,109,101,110,116,97,116,105,111,110,218,9, - 99,97,99,104,101,95,116,97,103,218,19,78,111,116,73,109, - 112,108,101,109,101,110,116,101,100,69,114,114,111,114,114,28, - 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,50, - 0,0,0,218,4,95,79,80,84,114,30,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,37,0, - 0,0,90,14,100,101,98,117,103,95,111,118,101,114,114,105, - 100,101,114,60,0,0,0,218,7,109,101,115,115,97,103,101, - 218,4,104,101,97,100,114,39,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,6,0,0, - 0,218,17,99,97,99,104,101,95,102,114,111,109,95,115,111, - 117,114,99,101,9,1,0,0,115,48,0,0,0,0,18,8, - 1,6,1,6,1,8,1,4,1,8,1,12,1,10,1,12, - 1,16,1,8,1,8,1,8,1,24,1,8,1,12,1,6, - 2,8,1,8,1,8,1,8,1,14,1,14,1,114,83,0, - 0,0,99,1,0,0,0,0,0,0,0,8,0,0,0,5, - 0,0,0,67,0,0,0,115,230,0,0,0,116,0,106,1, - 106,2,100,1,107,8,114,20,116,3,100,2,131,1,130,1, - 116,4,160,5,124,0,161,1,125,0,116,6,124,0,131,1, - 92,2,125,1,125,2,116,6,124,1,131,1,92,2,125,1, - 125,3,124,3,116,7,107,3,114,78,116,8,100,3,160,9, - 116,7,124,0,161,2,131,1,130,1,124,2,160,10,100,4, - 161,1,125,4,124,4,100,11,107,7,114,112,116,8,100,7, - 160,9,124,2,161,1,131,1,130,1,110,86,124,4,100,6, - 107,2,114,198,124,2,160,11,100,4,100,5,161,2,100,12, - 25,0,125,5,124,5,160,12,116,13,161,1,115,160,116,8, - 100,8,160,9,116,13,161,1,131,1,130,1,124,5,116,14, - 116,13,131,1,100,1,133,2,25,0,125,6,124,6,160,15, - 161,0,115,198,116,8,100,9,160,9,124,5,161,1,131,1, - 130,1,124,2,160,16,100,4,161,1,100,10,25,0,125,7, - 116,17,124,1,124,7,116,18,100,10,25,0,23,0,131,2, - 83,0,41,13,97,110,1,0,0,71,105,118,101,110,32,116, - 104,101,32,112,97,116,104,32,116,111,32,97,32,46,112,121, - 99,46,32,102,105,108,101,44,32,114,101,116,117,114,110,32, - 116,104,101,32,112,97,116,104,32,116,111,32,105,116,115,32, - 46,112,121,32,102,105,108,101,46,10,10,32,32,32,32,84, - 104,101,32,46,112,121,99,32,102,105,108,101,32,100,111,101, - 115,32,110,111,116,32,110,101,101,100,32,116,111,32,101,120, - 105,115,116,59,32,116,104,105,115,32,115,105,109,112,108,121, - 32,114,101,116,117,114,110,115,32,116,104,101,32,112,97,116, - 104,32,116,111,10,32,32,32,32,116,104,101,32,46,112,121, - 32,102,105,108,101,32,99,97,108,99,117,108,97,116,101,100, - 32,116,111,32,99,111,114,114,101,115,112,111,110,100,32,116, - 111,32,116,104,101,32,46,112,121,99,32,102,105,108,101,46, - 32,32,73,102,32,112,97,116,104,32,100,111,101,115,10,32, - 32,32,32,110,111,116,32,99,111,110,102,111,114,109,32,116, - 111,32,80,69,80,32,51,49,52,55,47,52,56,56,32,102, - 111,114,109,97,116,44,32,86,97,108,117,101,69,114,114,111, - 114,32,119,105,108,108,32,98,101,32,114,97,105,115,101,100, - 46,32,73,102,10,32,32,32,32,115,121,115,46,105,109,112, - 108,101,109,101,110,116,97,116,105,111,110,46,99,97,99,104, - 101,95,116,97,103,32,105,115,32,78,111,110,101,32,116,104, - 101,110,32,78,111,116,73,109,112,108,101,109,101,110,116,101, - 100,69,114,114,111,114,32,105,115,32,114,97,105,115,101,100, - 46,10,10,32,32,32,32,78,122,36,115,121,115,46,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,46,99,97,99, - 104,101,95,116,97,103,32,105,115,32,78,111,110,101,122,37, - 123,125,32,110,111,116,32,98,111,116,116,111,109,45,108,101, - 118,101,108,32,100,105,114,101,99,116,111,114,121,32,105,110, - 32,123,33,114,125,114,61,0,0,0,114,59,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,62,0,0,0,62,2,0, - 0,0,114,59,0,0,0,114,84,0,0,0,233,254,255,255, - 255,41,19,114,8,0,0,0,114,68,0,0,0,114,69,0, - 0,0,114,70,0,0,0,114,3,0,0,0,114,67,0,0, - 0,114,40,0,0,0,114,77,0,0,0,114,75,0,0,0, - 114,50,0,0,0,218,5,99,111,117,110,116,114,36,0,0, - 0,114,10,0,0,0,114,76,0,0,0,114,33,0,0,0, - 114,74,0,0,0,218,9,112,97,114,116,105,116,105,111,110, - 114,30,0,0,0,218,15,83,79,85,82,67,69,95,83,85, - 70,70,73,88,69,83,41,8,114,37,0,0,0,114,80,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,60,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,6,0,0,0,218,17,115,111,117,114,99,101,95,102, - 114,111,109,95,99,97,99,104,101,54,1,0,0,115,46,0, - 0,0,0,9,12,1,8,1,10,1,12,1,12,1,8,1, - 6,1,10,1,10,1,8,1,6,1,10,1,8,1,16,1, - 10,1,6,1,8,1,16,1,8,1,6,1,8,1,14,1, - 114,89,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,126,0,0,0,116, - 0,124,0,131,1,100,1,107,2,114,16,100,2,83,0,124, - 0,160,1,100,3,161,1,92,3,125,1,125,2,125,3,124, - 1,114,56,124,3,160,2,161,0,100,7,100,8,133,2,25, - 0,100,6,107,3,114,60,124,0,83,0,121,12,116,3,124, - 0,131,1,125,4,87,0,110,36,4,0,116,4,116,5,102, - 2,107,10,114,108,1,0,1,0,1,0,124,0,100,2,100, - 9,133,2,25,0,125,4,89,0,110,2,88,0,116,6,124, - 4,131,1,114,122,124,4,83,0,124,0,83,0,41,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,62,0, - 0,0,78,114,61,0,0,0,114,84,0,0,0,114,31,0, - 0,0,90,2,112,121,233,253,255,255,255,233,255,255,255,255, - 114,91,0,0,0,41,7,114,33,0,0,0,114,34,0,0, - 0,218,5,108,111,119,101,114,114,89,0,0,0,114,70,0, - 0,0,114,75,0,0,0,114,46,0,0,0,41,5,218,13, - 98,121,116,101,99,111,100,101,95,112,97,116,104,114,82,0, - 0,0,114,38,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,6,0,0,0,218,15, - 95,103,101,116,95,115,111,117,114,99,101,102,105,108,101,88, - 1,0,0,115,20,0,0,0,0,7,12,1,4,1,16,1, - 24,1,4,1,2,1,12,1,18,1,18,1,114,95,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,72,0,0,0,124,0,160,0,116, - 1,116,2,131,1,161,1,114,46,121,8,116,3,124,0,131, - 1,83,0,4,0,116,4,107,10,114,42,1,0,1,0,1, - 0,89,0,113,68,88,0,110,22,124,0,160,0,116,1,116, - 5,131,1,161,1,114,64,124,0,83,0,100,0,83,0,100, - 0,83,0,41,1,78,41,6,218,8,101,110,100,115,119,105, - 116,104,218,5,116,117,112,108,101,114,88,0,0,0,114,83, - 0,0,0,114,70,0,0,0,114,78,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,6,0,0,0,218,11,95,103,101,116,95,99, - 97,99,104,101,100,107,1,0,0,115,16,0,0,0,0,1, - 14,1,2,1,8,1,14,1,8,1,14,1,4,2,114,99, - 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,52,0,0,0,121,14,116, - 0,124,0,131,1,106,1,125,1,87,0,110,24,4,0,116, - 2,107,10,114,38,1,0,1,0,1,0,100,1,125,1,89, - 0,110,2,88,0,124,1,100,2,79,0,125,1,124,1,83, - 0,41,3,122,51,67,97,108,99,117,108,97,116,101,32,116, - 104,101,32,109,111,100,101,32,112,101,114,109,105,115,115,105, - 111,110,115,32,102,111,114,32,97,32,98,121,116,101,99,111, - 100,101,32,102,105,108,101,46,105,182,1,0,0,233,128,0, - 0,0,41,3,114,41,0,0,0,114,43,0,0,0,114,42, - 0,0,0,41,2,114,37,0,0,0,114,44,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,10, - 95,99,97,108,99,95,109,111,100,101,119,1,0,0,115,12, - 0,0,0,0,2,2,1,14,1,14,1,10,3,8,1,114, - 101,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,68,0,0,0,100,6, - 135,0,102,1,100,2,100,3,132,9,125,1,121,10,116,0, - 106,1,125,2,87,0,110,28,4,0,116,2,107,10,114,52, - 1,0,1,0,1,0,100,4,100,5,132,0,125,2,89,0, - 110,2,88,0,124,2,124,1,136,0,131,2,1,0,124,1, - 83,0,41,7,122,252,68,101,99,111,114,97,116,111,114,32, - 116,111,32,118,101,114,105,102,121,32,116,104,97,116,32,116, - 104,101,32,109,111,100,117,108,101,32,98,101,105,110,103,32, - 114,101,113,117,101,115,116,101,100,32,109,97,116,99,104,101, - 115,32,116,104,101,32,111,110,101,32,116,104,101,10,32,32, - 32,32,108,111,97,100,101,114,32,99,97,110,32,104,97,110, - 100,108,101,46,10,10,32,32,32,32,84,104,101,32,102,105, - 114,115,116,32,97,114,103,117,109,101,110,116,32,40,115,101, - 108,102,41,32,109,117,115,116,32,100,101,102,105,110,101,32, - 95,110,97,109,101,32,119,104,105,99,104,32,116,104,101,32, - 115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32, - 105,115,10,32,32,32,32,99,111,109,112,97,114,101,100,32, - 97,103,97,105,110,115,116,46,32,73,102,32,116,104,101,32, - 99,111,109,112,97,114,105,115,111,110,32,102,97,105,108,115, - 32,116,104,101,110,32,73,109,112,111,114,116,69,114,114,111, - 114,32,105,115,32,114,97,105,115,101,100,46,10,10,32,32, - 32,32,78,99,2,0,0,0,0,0,0,0,4,0,0,0, - 4,0,0,0,31,0,0,0,115,66,0,0,0,124,1,100, - 0,107,8,114,16,124,0,106,0,125,1,110,32,124,0,106, - 0,124,1,107,3,114,48,116,1,100,1,124,0,106,0,124, - 1,102,2,22,0,124,1,100,2,141,2,130,1,136,0,124, - 0,124,1,102,2,124,2,158,2,124,3,142,1,83,0,41, - 3,78,122,30,108,111,97,100,101,114,32,102,111,114,32,37, - 115,32,99,97,110,110,111,116,32,104,97,110,100,108,101,32, - 37,115,41,1,218,4,110,97,109,101,41,2,114,102,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,102,0,0,0,218,4,97,114,103, - 115,90,6,107,119,97,114,103,115,41,1,218,6,109,101,116, - 104,111,100,114,4,0,0,0,114,6,0,0,0,218,19,95, - 99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,112, - 101,114,139,1,0,0,115,12,0,0,0,0,1,8,1,8, - 1,10,1,4,1,18,1,122,40,95,99,104,101,99,107,95, - 110,97,109,101,46,60,108,111,99,97,108,115,62,46,95,99, - 104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101, - 114,99,2,0,0,0,0,0,0,0,3,0,0,0,7,0, - 0,0,83,0,0,0,115,60,0,0,0,120,40,100,5,68, - 0,93,32,125,2,116,0,124,1,124,2,131,2,114,6,116, - 1,124,0,124,2,116,2,124,1,124,2,131,2,131,3,1, - 0,113,6,87,0,124,0,106,3,160,4,124,1,106,3,161, - 1,1,0,100,0,83,0,41,6,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,4,114,108,0,0,0,114,109, - 0,0,0,114,110,0,0,0,114,111,0,0,0,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,55,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,218,5,95,119, - 114,97,112,150,1,0,0,115,8,0,0,0,0,1,10,1, - 10,1,22,1,122,26,95,99,104,101,99,107,95,110,97,109, - 101,46,60,108,111,99,97,108,115,62,46,95,119,114,97,112, - 41,1,78,41,3,218,10,95,98,111,111,116,115,116,114,97, - 112,114,117,0,0,0,218,9,78,97,109,101,69,114,114,111, - 114,41,3,114,106,0,0,0,114,107,0,0,0,114,117,0, - 0,0,114,4,0,0,0,41,1,114,106,0,0,0,114,6, - 0,0,0,218,11,95,99,104,101,99,107,95,110,97,109,101, - 131,1,0,0,115,14,0,0,0,0,8,14,7,2,1,10, - 1,14,2,14,5,10,1,114,120,0,0,0,99,2,0,0, - 0,0,0,0,0,5,0,0,0,6,0,0,0,67,0,0, - 0,115,60,0,0,0,124,0,160,0,124,1,161,1,92,2, - 125,2,125,3,124,2,100,1,107,8,114,56,116,1,124,3, - 131,1,114,56,100,2,125,4,116,2,160,3,124,4,160,4, - 124,3,100,3,25,0,161,1,116,5,161,2,1,0,124,2, - 83,0,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,62,0,0,0,41,6,218,11,102,105,110,100,95,108,111, - 97,100,101,114,114,33,0,0,0,114,63,0,0,0,114,64, - 0,0,0,114,50,0,0,0,218,13,73,109,112,111,114,116, - 87,97,114,110,105,110,103,41,5,114,104,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, + 90,34,100,49,100,50,132,0,90,35,100,51,100,52,132,0, + 90,36,100,53,100,54,132,0,90,37,100,102,100,55,100,56, + 132,1,90,38,100,103,100,58,100,59,132,1,90,39,100,104, + 100,61,100,62,132,1,90,40,100,63,100,64,132,0,90,41, + 101,42,131,0,90,43,100,105,100,33,101,43,100,65,156,2, + 100,66,100,67,132,3,90,44,71,0,100,68,100,69,132,0, + 100,69,131,2,90,45,71,0,100,70,100,71,132,0,100,71, + 131,2,90,46,71,0,100,72,100,73,132,0,100,73,101,46, + 131,3,90,47,71,0,100,74,100,75,132,0,100,75,131,2, + 90,48,71,0,100,76,100,77,132,0,100,77,101,48,101,47, + 131,4,90,49,71,0,100,78,100,79,132,0,100,79,101,48, + 101,46,131,4,90,50,103,0,90,51,71,0,100,80,100,81, + 132,0,100,81,101,48,101,46,131,4,90,52,71,0,100,82, + 100,83,132,0,100,83,131,2,90,53,71,0,100,84,100,85, + 132,0,100,85,131,2,90,54,71,0,100,86,100,87,132,0, + 100,87,131,2,90,55,71,0,100,88,100,89,132,0,100,89, + 131,2,90,56,100,106,100,90,100,91,132,1,90,57,100,92, + 100,93,132,0,90,58,100,94,100,95,132,0,90,59,100,96, + 100,97,132,0,90,60,100,33,83,0,41,107,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,3,0,0,0,3,0,0,0,115,60,0,0,0,116,0, + 106,1,160,2,116,3,161,1,114,48,116,0,106,1,160,2, + 116,4,161,1,114,30,100,1,137,0,110,4,100,2,137,0, + 135,0,102,1,100,3,100,4,132,8,125,0,110,8,100,5, + 100,4,132,0,125,0,124,0,83,0,41,6,78,90,12,80, + 89,84,72,79,78,67,65,83,69,79,75,115,12,0,0,0, + 80,89,84,72,79,78,67,65,83,69,79,75,99,0,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,19,0,0, + 0,115,10,0,0,0,136,0,116,0,106,1,107,6,83,0, + 41,1,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,41,2,218,3,95,111,115, + 90,7,101,110,118,105,114,111,110,169,0,41,1,218,3,107, + 101,121,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,37,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,83,0,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,6,0,0,0,114, + 7,0,0,0,41,0,0,0,115,2,0,0,0,0,2,41, + 5,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,218,35,95,67,65,83,69, + 95,73,78,83,69,78,83,73,84,73,86,69,95,80,76,65, + 84,70,79,82,77,83,95,83,84,82,95,75,69,89,41,1, + 114,7,0,0,0,114,4,0,0,0,41,1,114,5,0,0, + 0,114,6,0,0,0,218,16,95,109,97,107,101,95,114,101, + 108,97,120,95,99,97,115,101,30,0,0,0,115,14,0,0, + 0,0,1,12,1,12,1,6,2,4,2,14,4,8,3,114, + 13,0,0,0,99,1,0,0,0,0,0,0,0,1,0,0, + 0,4,0,0,0,67,0,0,0,115,20,0,0,0,116,0, + 124,0,131,1,100,1,64,0,160,1,100,2,100,3,161,2, + 83,0,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,6,0,0,0,218,7,95, + 119,95,108,111,110,103,47,0,0,0,115,2,0,0,0,0, + 2,114,19,0,0,0,99,1,0,0,0,0,0,0,0,1, + 0,0,0,4,0,0,0,67,0,0,0,115,12,0,0,0, + 116,0,160,1,124,0,100,1,161,2,83,0,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, + 15,0,0,0,41,2,114,16,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,6, + 0,0,0,218,7,95,114,95,108,111,110,103,52,0,0,0, + 115,2,0,0,0,0,2,114,21,0,0,0,99,0,0,0, + 0,0,0,0,0,1,0,0,0,4,0,0,0,71,0,0, + 0,115,20,0,0,0,116,0,160,1,100,1,100,2,132,0, + 124,0,68,0,131,1,161,1,83,0,41,3,122,31,82,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,5,0,0,0,83,0, + 0,0,115,26,0,0,0,103,0,124,0,93,18,125,1,124, + 1,114,4,124,1,160,0,116,1,161,1,145,2,113,4,83, + 0,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,6,0,0,0,250,10,60,108, + 105,115,116,99,111,109,112,62,59,0,0,0,115,2,0,0, + 0,6,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,6,0, + 0,0,218,10,95,112,97,116,104,95,106,111,105,110,57,0, + 0,0,115,4,0,0,0,0,2,10,1,114,30,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,96,0,0,0,116,0,116,1,131,1, + 100,1,107,2,114,36,124,0,160,2,116,3,161,1,92,3, + 125,1,125,2,125,3,124,1,124,3,102,2,83,0,120,50, + 116,4,124,0,131,1,68,0,93,38,125,4,124,4,116,1, + 107,6,114,46,124,0,106,5,124,4,100,1,100,2,141,2, + 92,2,125,1,125,3,124,1,124,3,102,2,83,0,113,46, + 87,0,100,3,124,0,102,2,83,0,41,4,122,32,82,101, + 112,108,97,99,101,109,101,110,116,32,102,111,114,32,111,115, + 46,112,97,116,104,46,115,112,108,105,116,40,41,46,233,1, + 0,0,0,41,1,90,8,109,97,120,115,112,108,105,116,218, + 0,41,6,218,3,108,101,110,114,23,0,0,0,218,10,114, + 112,97,114,116,105,116,105,111,110,114,27,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,18,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,6,0,0,0,218,11,95,112, + 97,116,104,95,115,112,108,105,116,63,0,0,0,115,16,0, + 0,0,0,2,12,1,16,1,8,1,14,1,8,1,18,1, + 12,1,114,40,0,0,0,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,10,0,0, + 0,116,0,160,1,124,0,161,1,83,0,41,1,122,126,83, + 116,97,116,32,116,104,101,32,112,97,116,104,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,37,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, + 218,10,95,112,97,116,104,95,115,116,97,116,75,0,0,0, + 115,2,0,0,0,0,7,114,41,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,48,0,0,0,121,12,116,0,124,0,131,1,125,2, + 87,0,110,20,4,0,116,1,107,10,114,32,1,0,1,0, + 1,0,100,1,83,0,88,0,124,2,106,2,100,2,64,0, + 124,1,107,2,83,0,41,3,122,49,84,101,115,116,32,119, + 104,101,116,104,101,114,32,116,104,101,32,112,97,116,104,32, + 105,115,32,116,104,101,32,115,112,101,99,105,102,105,101,100, + 32,109,111,100,101,32,116,121,112,101,46,70,105,0,240,0, + 0,41,3,114,41,0,0,0,218,7,79,83,69,114,114,111, + 114,218,7,115,116,95,109,111,100,101,41,3,114,37,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,6,0,0, + 0,218,18,95,112,97,116,104,95,105,115,95,109,111,100,101, + 95,116,121,112,101,85,0,0,0,115,10,0,0,0,0,2, + 2,1,12,1,14,1,6,1,114,45,0,0,0,99,1,0, + 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, + 0,0,115,10,0,0,0,116,0,124,0,100,1,131,2,83, + 0,41,2,122,31,82,101,112,108,97,99,101,109,101,110,116, + 32,102,111,114,32,111,115,46,112,97,116,104,46,105,115,102, + 105,108,101,46,105,0,128,0,0,41,1,114,45,0,0,0, + 41,1,114,37,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,218,12,95,112,97,116,104,95,105,115, + 102,105,108,101,94,0,0,0,115,2,0,0,0,0,2,114, + 46,0,0,0,99,1,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,115,22,0,0,0,124,0, + 115,12,116,0,160,1,161,0,125,0,116,2,124,0,100,1, + 131,2,83,0,41,2,122,30,82,101,112,108,97,99,101,109, + 101,110,116,32,102,111,114,32,111,115,46,112,97,116,104,46, + 105,115,100,105,114,46,105,0,64,0,0,41,3,114,3,0, + 0,0,218,6,103,101,116,99,119,100,114,45,0,0,0,41, + 1,114,37,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,218,11,95,112,97,116,104,95,105,115,100, + 105,114,99,0,0,0,115,6,0,0,0,0,2,4,1,8, + 1,114,48,0,0,0,233,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,162,0,0,0,100,1,160,0,124,0,116,1,124,0,131, + 1,161,2,125,3,116,2,160,3,124,3,116,2,106,4,116, + 2,106,5,66,0,116,2,106,6,66,0,124,2,100,2,64, + 0,161,3,125,4,121,50,116,7,160,8,124,4,100,3,161, + 2,143,16,125,5,124,5,160,9,124,1,161,1,1,0,87, + 0,100,4,81,0,82,0,88,0,116,2,160,10,124,3,124, + 0,161,2,1,0,87,0,110,58,4,0,116,11,107,10,114, + 156,1,0,1,0,1,0,121,14,116,2,160,12,124,3,161, + 1,1,0,87,0,110,20,4,0,116,11,107,10,114,148,1, + 0,1,0,1,0,89,0,110,2,88,0,130,0,89,0,110, + 2,88,0,100,4,83,0,41,5,122,162,66,101,115,116,45, + 101,102,102,111,114,116,32,102,117,110,99,116,105,111,110,32, + 116,111,32,119,114,105,116,101,32,100,97,116,97,32,116,111, + 32,97,32,112,97,116,104,32,97,116,111,109,105,99,97,108, + 108,121,46,10,32,32,32,32,66,101,32,112,114,101,112,97, + 114,101,100,32,116,111,32,104,97,110,100,108,101,32,97,32, + 70,105,108,101,69,120,105,115,116,115,69,114,114,111,114,32, + 105,102,32,99,111,110,99,117,114,114,101,110,116,32,119,114, + 105,116,105,110,103,32,111,102,32,116,104,101,10,32,32,32, + 32,116,101,109,112,111,114,97,114,121,32,102,105,108,101,32, + 105,115,32,97,116,116,101,109,112,116,101,100,46,122,5,123, + 125,46,123,125,105,182,1,0,0,90,2,119,98,78,41,13, + 218,6,102,111,114,109,97,116,218,2,105,100,114,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, + 42,0,0,0,90,6,117,110,108,105,110,107,41,6,114,37, + 0,0,0,218,4,100,97,116,97,114,44,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,6,0,0, + 0,218,13,95,119,114,105,116,101,95,97,116,111,109,105,99, + 106,0,0,0,115,26,0,0,0,0,5,16,1,6,1,26, + 1,2,3,14,1,20,1,16,1,14,1,2,1,14,1,14, + 1,6,1,114,58,0,0,0,105,64,13,0,0,233,2,0, + 0,0,114,15,0,0,0,115,2,0,0,0,13,10,90,11, + 95,95,112,121,99,97,99,104,101,95,95,122,4,111,112,116, + 45,122,3,46,112,121,122,4,46,112,121,99,78,41,1,218, + 12,111,112,116,105,109,105,122,97,116,105,111,110,99,2,0, + 0,0,1,0,0,0,11,0,0,0,6,0,0,0,67,0, + 0,0,115,244,0,0,0,124,1,100,1,107,9,114,52,116, + 0,160,1,100,2,116,2,161,2,1,0,124,2,100,1,107, + 9,114,40,100,3,125,3,116,3,124,3,131,1,130,1,124, + 1,114,48,100,4,110,2,100,5,125,2,116,4,160,5,124, + 0,161,1,125,0,116,6,124,0,131,1,92,2,125,4,125, + 5,124,5,160,7,100,6,161,1,92,3,125,6,125,7,125, + 8,116,8,106,9,106,10,125,9,124,9,100,1,107,8,114, + 114,116,11,100,7,131,1,130,1,100,4,160,12,124,6,114, + 126,124,6,110,2,124,8,124,7,124,9,103,3,161,1,125, + 10,124,2,100,1,107,8,114,172,116,8,106,13,106,14,100, + 8,107,2,114,164,100,4,125,2,110,8,116,8,106,13,106, + 14,125,2,116,15,124,2,131,1,125,2,124,2,100,4,107, + 3,114,224,124,2,160,16,161,0,115,210,116,17,100,9,160, + 18,124,2,161,1,131,1,130,1,100,10,160,18,124,10,116, + 19,124,2,161,3,125,10,116,20,124,4,116,21,124,10,116, + 22,100,8,25,0,23,0,131,3,83,0,41,11,97,254,2, + 0,0,71,105,118,101,110,32,116,104,101,32,112,97,116,104, + 32,116,111,32,97,32,46,112,121,32,102,105,108,101,44,32, + 114,101,116,117,114,110,32,116,104,101,32,112,97,116,104,32, + 116,111,32,105,116,115,32,46,112,121,99,32,102,105,108,101, + 46,10,10,32,32,32,32,84,104,101,32,46,112,121,32,102, + 105,108,101,32,100,111,101,115,32,110,111,116,32,110,101,101, + 100,32,116,111,32,101,120,105,115,116,59,32,116,104,105,115, + 32,115,105,109,112,108,121,32,114,101,116,117,114,110,115,32, + 116,104,101,32,112,97,116,104,32,116,111,32,116,104,101,10, + 32,32,32,32,46,112,121,99,32,102,105,108,101,32,99,97, + 108,99,117,108,97,116,101,100,32,97,115,32,105,102,32,116, + 104,101,32,46,112,121,32,102,105,108,101,32,119,101,114,101, + 32,105,109,112,111,114,116,101,100,46,10,10,32,32,32,32, + 84,104,101,32,39,111,112,116,105,109,105,122,97,116,105,111, + 110,39,32,112,97,114,97,109,101,116,101,114,32,99,111,110, + 116,114,111,108,115,32,116,104,101,32,112,114,101,115,117,109, + 101,100,32,111,112,116,105,109,105,122,97,116,105,111,110,32, + 108,101,118,101,108,32,111,102,10,32,32,32,32,116,104,101, + 32,98,121,116,101,99,111,100,101,32,102,105,108,101,46,32, + 73,102,32,39,111,112,116,105,109,105,122,97,116,105,111,110, + 39,32,105,115,32,110,111,116,32,78,111,110,101,44,32,116, + 104,101,32,115,116,114,105,110,103,32,114,101,112,114,101,115, + 101,110,116,97,116,105,111,110,10,32,32,32,32,111,102,32, + 116,104,101,32,97,114,103,117,109,101,110,116,32,105,115,32, + 116,97,107,101,110,32,97,110,100,32,118,101,114,105,102,105, + 101,100,32,116,111,32,98,101,32,97,108,112,104,97,110,117, + 109,101,114,105,99,32,40,101,108,115,101,32,86,97,108,117, + 101,69,114,114,111,114,10,32,32,32,32,105,115,32,114,97, + 105,115,101,100,41,46,10,10,32,32,32,32,84,104,101,32, + 100,101,98,117,103,95,111,118,101,114,114,105,100,101,32,112, + 97,114,97,109,101,116,101,114,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,46,32,73,102,32,100,101,98,117,103, + 95,111,118,101,114,114,105,100,101,32,105,115,32,110,111,116, + 32,78,111,110,101,44,10,32,32,32,32,97,32,84,114,117, + 101,32,118,97,108,117,101,32,105,115,32,116,104,101,32,115, + 97,109,101,32,97,115,32,115,101,116,116,105,110,103,32,39, + 111,112,116,105,109,105,122,97,116,105,111,110,39,32,116,111, + 32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110, + 103,10,32,32,32,32,119,104,105,108,101,32,97,32,70,97, + 108,115,101,32,118,97,108,117,101,32,105,115,32,101,113,117, + 105,118,97,108,101,110,116,32,116,111,32,115,101,116,116,105, + 110,103,32,39,111,112,116,105,109,105,122,97,116,105,111,110, + 39,32,116,111,32,39,49,39,46,10,10,32,32,32,32,73, + 102,32,115,121,115,46,105,109,112,108,101,109,101,110,116,97, + 116,105,111,110,46,99,97,99,104,101,95,116,97,103,32,105, + 115,32,78,111,110,101,32,116,104,101,110,32,78,111,116,73, + 109,112,108,101,109,101,110,116,101,100,69,114,114,111,114,32, + 105,115,32,114,97,105,115,101,100,46,10,10,32,32,32,32, + 78,122,70,116,104,101,32,100,101,98,117,103,95,111,118,101, + 114,114,105,100,101,32,112,97,114,97,109,101,116,101,114,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,59,32,117, + 115,101,32,39,111,112,116,105,109,105,122,97,116,105,111,110, + 39,32,105,110,115,116,101,97,100,122,50,100,101,98,117,103, + 95,111,118,101,114,114,105,100,101,32,111,114,32,111,112,116, + 105,109,105,122,97,116,105,111,110,32,109,117,115,116,32,98, + 101,32,115,101,116,32,116,111,32,78,111,110,101,114,32,0, + 0,0,114,31,0,0,0,218,1,46,122,36,115,121,115,46, + 105,109,112,108,101,109,101,110,116,97,116,105,111,110,46,99, + 97,99,104,101,95,116,97,103,32,105,115,32,78,111,110,101, + 233,0,0,0,0,122,24,123,33,114,125,32,105,115,32,110, + 111,116,32,97,108,112,104,97,110,117,109,101,114,105,99,122, + 7,123,125,46,123,125,123,125,41,23,218,9,95,119,97,114, + 110,105,110,103,115,218,4,119,97,114,110,218,18,68,101,112, + 114,101,99,97,116,105,111,110,87,97,114,110,105,110,103,218, + 9,84,121,112,101,69,114,114,111,114,114,3,0,0,0,218, + 6,102,115,112,97,116,104,114,40,0,0,0,114,34,0,0, + 0,114,8,0,0,0,218,14,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,218,9,99,97,99,104,101,95,116,97, + 103,218,19,78,111,116,73,109,112,108,101,109,101,110,116,101, + 100,69,114,114,111,114,114,28,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,50,0,0,0,218,4,95,79,80, + 84,114,30,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,37,0,0,0,90,14,100,101,98,117, + 103,95,111,118,101,114,114,105,100,101,114,60,0,0,0,218, + 7,109,101,115,115,97,103,101,218,4,104,101,97,100,114,39, + 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,6,0,0,0,218,17,99,97,99,104,101, + 95,102,114,111,109,95,115,111,117,114,99,101,10,1,0,0, + 115,48,0,0,0,0,18,8,1,6,1,6,1,8,1,4, + 1,8,1,12,1,10,1,12,1,16,1,8,1,8,1,8, + 1,24,1,8,1,12,1,6,2,8,1,8,1,8,1,8, + 1,14,1,14,1,114,83,0,0,0,99,1,0,0,0,0, + 0,0,0,8,0,0,0,5,0,0,0,67,0,0,0,115, + 230,0,0,0,116,0,106,1,106,2,100,1,107,8,114,20, + 116,3,100,2,131,1,130,1,116,4,160,5,124,0,161,1, + 125,0,116,6,124,0,131,1,92,2,125,1,125,2,116,6, + 124,1,131,1,92,2,125,1,125,3,124,3,116,7,107,3, + 114,78,116,8,100,3,160,9,116,7,124,0,161,2,131,1, + 130,1,124,2,160,10,100,4,161,1,125,4,124,4,100,11, + 107,7,114,112,116,8,100,7,160,9,124,2,161,1,131,1, + 130,1,110,86,124,4,100,6,107,2,114,198,124,2,160,11, + 100,4,100,5,161,2,100,12,25,0,125,5,124,5,160,12, + 116,13,161,1,115,160,116,8,100,8,160,9,116,13,161,1, + 131,1,130,1,124,5,116,14,116,13,131,1,100,1,133,2, + 25,0,125,6,124,6,160,15,161,0,115,198,116,8,100,9, + 160,9,124,5,161,1,131,1,130,1,124,2,160,16,100,4, + 161,1,100,10,25,0,125,7,116,17,124,1,124,7,116,18, + 100,10,25,0,23,0,131,2,83,0,41,13,97,110,1,0, + 0,71,105,118,101,110,32,116,104,101,32,112,97,116,104,32, + 116,111,32,97,32,46,112,121,99,46,32,102,105,108,101,44, + 32,114,101,116,117,114,110,32,116,104,101,32,112,97,116,104, + 32,116,111,32,105,116,115,32,46,112,121,32,102,105,108,101, + 46,10,10,32,32,32,32,84,104,101,32,46,112,121,99,32, + 102,105,108,101,32,100,111,101,115,32,110,111,116,32,110,101, + 101,100,32,116,111,32,101,120,105,115,116,59,32,116,104,105, + 115,32,115,105,109,112,108,121,32,114,101,116,117,114,110,115, + 32,116,104,101,32,112,97,116,104,32,116,111,10,32,32,32, + 32,116,104,101,32,46,112,121,32,102,105,108,101,32,99,97, + 108,99,117,108,97,116,101,100,32,116,111,32,99,111,114,114, + 101,115,112,111,110,100,32,116,111,32,116,104,101,32,46,112, + 121,99,32,102,105,108,101,46,32,32,73,102,32,112,97,116, + 104,32,100,111,101,115,10,32,32,32,32,110,111,116,32,99, + 111,110,102,111,114,109,32,116,111,32,80,69,80,32,51,49, + 52,55,47,52,56,56,32,102,111,114,109,97,116,44,32,86, + 97,108,117,101,69,114,114,111,114,32,119,105,108,108,32,98, + 101,32,114,97,105,115,101,100,46,32,73,102,10,32,32,32, + 32,115,121,115,46,105,109,112,108,101,109,101,110,116,97,116, + 105,111,110,46,99,97,99,104,101,95,116,97,103,32,105,115, + 32,78,111,110,101,32,116,104,101,110,32,78,111,116,73,109, + 112,108,101,109,101,110,116,101,100,69,114,114,111,114,32,105, + 115,32,114,97,105,115,101,100,46,10,10,32,32,32,32,78, + 122,36,115,121,115,46,105,109,112,108,101,109,101,110,116,97, + 116,105,111,110,46,99,97,99,104,101,95,116,97,103,32,105, + 115,32,78,111,110,101,122,37,123,125,32,110,111,116,32,98, + 111,116,116,111,109,45,108,101,118,101,108,32,100,105,114,101, + 99,116,111,114,121,32,105,110,32,123,33,114,125,114,61,0, + 0,0,114,59,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,62,0,0,0,62,2,0,0,0,114,59,0,0,0,114, + 84,0,0,0,233,254,255,255,255,41,19,114,8,0,0,0, + 114,68,0,0,0,114,69,0,0,0,114,70,0,0,0,114, + 3,0,0,0,114,67,0,0,0,114,40,0,0,0,114,77, + 0,0,0,114,75,0,0,0,114,50,0,0,0,218,5,99, + 111,117,110,116,114,36,0,0,0,114,10,0,0,0,114,76, + 0,0,0,114,33,0,0,0,114,74,0,0,0,218,9,112, + 97,114,116,105,116,105,111,110,114,30,0,0,0,218,15,83, + 79,85,82,67,69,95,83,85,70,70,73,88,69,83,41,8, + 114,37,0,0,0,114,80,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,60,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,6,0,0,0,218,17, - 95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105, - 109,159,1,0,0,115,10,0,0,0,0,10,14,1,16,1, - 4,1,22,1,114,127,0,0,0,99,4,0,0,0,0,0, - 0,0,11,0,0,0,20,0,0,0,67,0,0,0,115,136, - 1,0,0,105,0,125,4,124,2,100,1,107,9,114,22,124, - 2,124,4,100,2,60,0,110,4,100,3,125,2,124,3,100, - 1,107,9,114,42,124,3,124,4,100,4,60,0,124,0,100, - 1,100,5,133,2,25,0,125,5,124,0,100,5,100,6,133, - 2,25,0,125,6,124,0,100,6,100,7,133,2,25,0,125, - 7,124,5,116,0,107,3,114,124,100,8,160,1,124,2,124, - 5,161,2,125,8,116,2,160,3,100,9,124,8,161,2,1, - 0,116,4,124,8,102,1,124,4,142,1,130,1,110,86,116, - 5,124,6,131,1,100,5,107,3,114,168,100,10,160,1,124, - 2,161,1,125,8,116,2,160,3,100,9,124,8,161,2,1, - 0,116,6,124,8,131,1,130,1,110,42,116,5,124,7,131, - 1,100,5,107,3,114,210,100,11,160,1,124,2,161,1,125, - 8,116,2,160,3,100,9,124,8,161,2,1,0,116,6,124, - 8,131,1,130,1,124,1,100,1,107,9,144,1,114,124,121, - 16,116,7,124,1,100,12,25,0,131,1,125,9,87,0,110, - 22,4,0,116,8,107,10,144,1,114,2,1,0,1,0,1, - 0,89,0,110,50,88,0,116,9,124,6,131,1,124,9,107, - 3,144,1,114,52,100,13,160,1,124,2,161,1,125,8,116, - 2,160,3,100,9,124,8,161,2,1,0,116,4,124,8,102, - 1,124,4,142,1,130,1,121,16,124,1,100,14,25,0,100, - 15,64,0,125,10,87,0,110,22,4,0,116,8,107,10,144, - 1,114,90,1,0,1,0,1,0,89,0,110,34,88,0,116, - 9,124,7,131,1,124,10,107,3,144,1,114,124,116,4,100, - 13,160,1,124,2,161,1,102,1,124,4,142,1,130,1,124, - 0,100,7,100,1,133,2,25,0,83,0,41,16,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,102,0, - 0,0,122,10,60,98,121,116,101,99,111,100,101,62,114,37, - 0,0,0,114,14,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,2,123,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,10,218,12,77,65,71, - 73,67,95,78,85,77,66,69,82,114,50,0,0,0,114,118, - 0,0,0,218,16,95,118,101,114,98,111,115,101,95,109,101, - 115,115,97,103,101,114,103,0,0,0,114,33,0,0,0,218, - 8,69,79,70,69,114,114,111,114,114,16,0,0,0,218,8, - 75,101,121,69,114,114,111,114,114,21,0,0,0,41,11,114, - 56,0,0,0,218,12,115,111,117,114,99,101,95,115,116,97, - 116,115,114,102,0,0,0,114,37,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,79,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,6,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,176,1,0,0,115,76,0,0,0,0,11,4,1, - 8,1,10,3,4,1,8,1,8,1,12,1,12,1,12,1, - 8,1,12,1,12,1,14,1,12,1,10,1,12,1,10,1, - 12,1,10,1,12,1,8,1,10,1,2,1,16,1,16,1, - 6,2,14,1,10,1,12,1,12,1,2,1,16,1,16,1, - 6,2,14,1,12,1,6,1,114,139,0,0,0,99,4,0, - 0,0,0,0,0,0,5,0,0,0,5,0,0,0,67,0, - 0,0,115,80,0,0,0,116,0,160,1,124,0,161,1,125, - 4,116,2,124,4,116,3,131,2,114,56,116,4,160,5,100, - 1,124,2,161,2,1,0,124,3,100,2,107,9,114,52,116, - 6,160,7,124,4,124,3,161,2,1,0,124,4,83,0,116, - 8,100,3,160,9,124,2,161,1,124,1,124,2,100,4,141, - 3,130,1,100,2,83,0,41,5,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,41,2,114,102,0,0,0,114, - 37,0,0,0,41,10,218,7,109,97,114,115,104,97,108,90, - 5,108,111,97,100,115,218,10,105,115,105,110,115,116,97,110, - 99,101,218,10,95,99,111,100,101,95,116,121,112,101,114,118, - 0,0,0,114,133,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,103,0,0,0,114,50,0,0,0,41,5,114,56,0,0, - 0,114,102,0,0,0,114,93,0,0,0,114,94,0,0,0, - 218,4,99,111,100,101,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,17,95,99,111,109,112,105,108,101,95, - 98,121,116,101,99,111,100,101,231,1,0,0,115,16,0,0, - 0,0,2,10,1,10,1,12,1,8,1,12,1,4,2,10, - 1,114,145,0,0,0,114,62,0,0,0,99,3,0,0,0, - 0,0,0,0,4,0,0,0,5,0,0,0,67,0,0,0, - 115,56,0,0,0,116,0,116,1,131,1,125,3,124,3,160, - 2,116,3,124,1,131,1,161,1,1,0,124,3,160,2,116, - 3,124,2,131,1,161,1,1,0,124,3,160,2,116,4,160, - 5,124,0,161,1,161,1,1,0,124,3,83,0,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,132, - 0,0,0,218,6,101,120,116,101,110,100,114,19,0,0,0, - 114,140,0,0,0,90,5,100,117,109,112,115,41,4,114,144, - 0,0,0,114,130,0,0,0,114,138,0,0,0,114,56,0, + 115,111,117,114,99,101,95,102,114,111,109,95,99,97,99,104, + 101,55,1,0,0,115,46,0,0,0,0,9,12,1,8,1, + 10,1,12,1,12,1,8,1,6,1,10,1,10,1,8,1, + 6,1,10,1,8,1,16,1,10,1,6,1,8,1,16,1, + 8,1,6,1,8,1,14,1,114,89,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,126,0,0,0,116,0,124,0,131,1,100,1,107, + 2,114,16,100,2,83,0,124,0,160,1,100,3,161,1,92, + 3,125,1,125,2,125,3,124,1,114,56,124,3,160,2,161, + 0,100,7,100,8,133,2,25,0,100,6,107,3,114,60,124, + 0,83,0,121,12,116,3,124,0,131,1,125,4,87,0,110, + 36,4,0,116,4,116,5,102,2,107,10,114,108,1,0,1, + 0,1,0,124,0,100,2,100,9,133,2,25,0,125,4,89, + 0,110,2,88,0,116,6,124,4,131,1,114,122,124,4,83, + 0,124,0,83,0,41,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,62,0,0,0,78,114,61,0,0,0, + 114,84,0,0,0,114,31,0,0,0,90,2,112,121,233,253, + 255,255,255,233,255,255,255,255,114,91,0,0,0,41,7,114, + 33,0,0,0,114,34,0,0,0,218,5,108,111,119,101,114, + 114,89,0,0,0,114,70,0,0,0,114,75,0,0,0,114, + 46,0,0,0,41,5,218,13,98,121,116,101,99,111,100,101, + 95,112,97,116,104,114,82,0,0,0,114,38,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,6,0,0,0,218,15,95,103,101,116,95,115,111,117, + 114,99,101,102,105,108,101,89,1,0,0,115,20,0,0,0, + 0,7,12,1,4,1,16,1,24,1,4,1,2,1,12,1, + 18,1,18,1,114,95,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,72, + 0,0,0,124,0,160,0,116,1,116,2,131,1,161,1,114, + 46,121,8,116,3,124,0,131,1,83,0,4,0,116,4,107, + 10,114,42,1,0,1,0,1,0,89,0,113,68,88,0,110, + 22,124,0,160,0,116,1,116,5,131,1,161,1,114,64,124, + 0,83,0,100,0,83,0,100,0,83,0,41,1,78,41,6, + 218,8,101,110,100,115,119,105,116,104,218,5,116,117,112,108, + 101,114,88,0,0,0,114,83,0,0,0,114,70,0,0,0, + 114,78,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,6,0,0,0, + 218,11,95,103,101,116,95,99,97,99,104,101,100,108,1,0, + 0,115,16,0,0,0,0,1,14,1,2,1,8,1,14,1, + 8,1,14,1,4,2,114,99,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,52,0,0,0,121,14,116,0,124,0,131,1,106,1,125, + 1,87,0,110,24,4,0,116,2,107,10,114,38,1,0,1, + 0,1,0,100,1,125,1,89,0,110,2,88,0,124,1,100, + 2,79,0,125,1,124,1,83,0,41,3,122,51,67,97,108, + 99,117,108,97,116,101,32,116,104,101,32,109,111,100,101,32, + 112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32, + 97,32,98,121,116,101,99,111,100,101,32,102,105,108,101,46, + 105,182,1,0,0,233,128,0,0,0,41,3,114,41,0,0, + 0,114,43,0,0,0,114,42,0,0,0,41,2,114,37,0, + 0,0,114,44,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,218,10,95,99,97,108,99,95,109,111, + 100,101,120,1,0,0,115,12,0,0,0,0,2,2,1,14, + 1,14,1,10,3,8,1,114,101,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,68,0,0,0,100,6,135,0,102,1,100,2,100,3, + 132,9,125,1,121,10,116,0,106,1,125,2,87,0,110,28, + 4,0,116,2,107,10,114,52,1,0,1,0,1,0,100,4, + 100,5,132,0,125,2,89,0,110,2,88,0,124,2,124,1, + 136,0,131,2,1,0,124,1,83,0,41,7,122,252,68,101, + 99,111,114,97,116,111,114,32,116,111,32,118,101,114,105,102, + 121,32,116,104,97,116,32,116,104,101,32,109,111,100,117,108, + 101,32,98,101,105,110,103,32,114,101,113,117,101,115,116,101, + 100,32,109,97,116,99,104,101,115,32,116,104,101,32,111,110, + 101,32,116,104,101,10,32,32,32,32,108,111,97,100,101,114, + 32,99,97,110,32,104,97,110,100,108,101,46,10,10,32,32, + 32,32,84,104,101,32,102,105,114,115,116,32,97,114,103,117, + 109,101,110,116,32,40,115,101,108,102,41,32,109,117,115,116, + 32,100,101,102,105,110,101,32,95,110,97,109,101,32,119,104, + 105,99,104,32,116,104,101,32,115,101,99,111,110,100,32,97, + 114,103,117,109,101,110,116,32,105,115,10,32,32,32,32,99, + 111,109,112,97,114,101,100,32,97,103,97,105,110,115,116,46, + 32,73,102,32,116,104,101,32,99,111,109,112,97,114,105,115, + 111,110,32,102,97,105,108,115,32,116,104,101,110,32,73,109, + 112,111,114,116,69,114,114,111,114,32,105,115,32,114,97,105, + 115,101,100,46,10,10,32,32,32,32,78,99,2,0,0,0, + 0,0,0,0,4,0,0,0,4,0,0,0,31,0,0,0, + 115,66,0,0,0,124,1,100,0,107,8,114,16,124,0,106, + 0,125,1,110,32,124,0,106,0,124,1,107,3,114,48,116, + 1,100,1,124,0,106,0,124,1,102,2,22,0,124,1,100, + 2,141,2,130,1,136,0,124,0,124,1,102,2,124,2,158, + 2,124,3,142,1,83,0,41,3,78,122,30,108,111,97,100, + 101,114,32,102,111,114,32,37,115,32,99,97,110,110,111,116, + 32,104,97,110,100,108,101,32,37,115,41,1,218,4,110,97, + 109,101,41,2,114,102,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,102, + 0,0,0,218,4,97,114,103,115,90,6,107,119,97,114,103, + 115,41,1,218,6,109,101,116,104,111,100,114,4,0,0,0, + 114,6,0,0,0,218,19,95,99,104,101,99,107,95,110,97, + 109,101,95,119,114,97,112,112,101,114,140,1,0,0,115,12, + 0,0,0,0,1,8,1,8,1,10,1,4,1,18,1,122, + 40,95,99,104,101,99,107,95,110,97,109,101,46,60,108,111, + 99,97,108,115,62,46,95,99,104,101,99,107,95,110,97,109, + 101,95,119,114,97,112,112,101,114,99,2,0,0,0,0,0, + 0,0,3,0,0,0,7,0,0,0,83,0,0,0,115,60, + 0,0,0,120,40,100,5,68,0,93,32,125,2,116,0,124, + 1,124,2,131,2,114,6,116,1,124,0,124,2,116,2,124, + 1,124,2,131,2,131,3,1,0,113,6,87,0,124,0,106, + 3,160,4,124,1,106,3,161,1,1,0,100,0,83,0,41, + 6,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, + 4,114,108,0,0,0,114,109,0,0,0,114,110,0,0,0, + 114,111,0,0,0,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,55,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,218,5,95,119,114,97,112,151,1,0,0,115, + 8,0,0,0,0,1,10,1,10,1,22,1,122,26,95,99, + 104,101,99,107,95,110,97,109,101,46,60,108,111,99,97,108, + 115,62,46,95,119,114,97,112,41,1,78,41,3,218,10,95, + 98,111,111,116,115,116,114,97,112,114,117,0,0,0,218,9, + 78,97,109,101,69,114,114,111,114,41,3,114,106,0,0,0, + 114,107,0,0,0,114,117,0,0,0,114,4,0,0,0,41, + 1,114,106,0,0,0,114,6,0,0,0,218,11,95,99,104, + 101,99,107,95,110,97,109,101,132,1,0,0,115,14,0,0, + 0,0,8,14,7,2,1,10,1,14,2,14,5,10,1,114, + 120,0,0,0,99,2,0,0,0,0,0,0,0,5,0,0, + 0,6,0,0,0,67,0,0,0,115,60,0,0,0,124,0, + 160,0,124,1,161,1,92,2,125,2,125,3,124,2,100,1, + 107,8,114,56,116,1,124,3,131,1,114,56,100,2,125,4, + 116,2,160,3,124,4,160,4,124,3,100,3,25,0,161,1, + 116,5,161,2,1,0,124,2,83,0,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,62,0,0,0,41,6,218, + 11,102,105,110,100,95,108,111,97,100,101,114,114,33,0,0, + 0,114,63,0,0,0,114,64,0,0,0,114,50,0,0,0, + 218,13,73,109,112,111,114,116,87,97,114,110,105,110,103,41, + 5,114,104,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,6,0,0,0,218,17,95,102,105,110,100,95,109,111, + 100,117,108,101,95,115,104,105,109,160,1,0,0,115,10,0, + 0,0,0,10,14,1,16,1,4,1,22,1,114,127,0,0, + 0,99,3,0,0,0,0,0,0,0,6,0,0,0,4,0, + 0,0,67,0,0,0,115,158,0,0,0,124,0,100,1,100, + 2,133,2,25,0,125,3,124,3,116,0,107,3,114,60,100, + 3,124,1,155,2,100,4,124,3,155,2,157,4,125,4,116, + 1,160,2,100,5,124,4,161,2,1,0,116,3,124,4,102, + 1,124,2,142,1,130,1,116,4,124,0,131,1,100,6,107, + 0,114,102,100,7,124,1,155,2,157,2,125,4,116,1,160, + 2,100,5,124,4,161,2,1,0,116,5,124,4,131,1,130, + 1,116,6,124,0,100,2,100,8,133,2,25,0,131,1,125, + 5,124,5,100,12,64,0,114,154,100,10,124,5,155,2,100, + 11,124,1,155,2,157,4,125,4,116,3,124,4,102,1,124, + 2,142,1,130,1,124,5,83,0,41,13,97,84,2,0,0, + 80,101,114,102,111,114,109,32,98,97,115,105,99,32,118,97, + 108,105,100,105,116,121,32,99,104,101,99,107,105,110,103,32, + 111,102,32,97,32,112,121,99,32,104,101,97,100,101,114,32, + 97,110,100,32,114,101,116,117,114,110,32,116,104,101,32,102, + 108,97,103,115,32,102,105,101,108,100,44,10,32,32,32,32, + 119,104,105,99,104,32,100,101,116,101,114,109,105,110,101,115, + 32,104,111,119,32,116,104,101,32,112,121,99,32,115,104,111, + 117,108,100,32,98,101,32,102,117,114,116,104,101,114,32,118, + 97,108,105,100,97,116,101,100,32,97,103,97,105,110,115,116, + 32,116,104,101,32,115,111,117,114,99,101,46,10,10,32,32, + 32,32,42,100,97,116,97,42,32,105,115,32,116,104,101,32, + 99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32, + 112,121,99,32,102,105,108,101,46,32,40,79,110,108,121,32, + 116,104,101,32,102,105,114,115,116,32,49,54,32,98,121,116, + 101,115,32,97,114,101,10,32,32,32,32,114,101,113,117,105, + 114,101,100,44,32,116,104,111,117,103,104,46,41,10,10,32, + 32,32,32,42,110,97,109,101,42,32,105,115,32,116,104,101, + 32,110,97,109,101,32,111,102,32,116,104,101,32,109,111,100, + 117,108,101,32,98,101,105,110,103,32,105,109,112,111,114,116, + 101,100,46,32,73,116,32,105,115,32,117,115,101,100,32,102, + 111,114,32,108,111,103,103,105,110,103,46,10,10,32,32,32, + 32,42,101,120,99,95,100,101,116,97,105,108,115,42,32,105, + 115,32,97,32,100,105,99,116,105,111,110,97,114,121,32,112, + 97,115,115,101,100,32,116,111,32,73,109,112,111,114,116,69, + 114,114,111,114,32,105,102,32,105,116,32,114,97,105,115,101, + 100,32,102,111,114,10,32,32,32,32,105,109,112,114,111,118, + 101,100,32,100,101,98,117,103,103,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,119, + 104,101,110,32,116,104,101,32,102,108,97,103,115,10,32,32, + 32,32,102,105,101,108,100,32,105,115,32,105,110,118,97,108, + 105,100,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,32,116,114,117,110,99,97,116,101,100,46,10,10, + 32,32,32,32,78,114,14,0,0,0,122,20,98,97,100,32, + 109,97,103,105,99,32,110,117,109,98,101,114,32,105,110,32, + 122,2,58,32,122,2,123,125,233,16,0,0,0,122,40,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,112,121,99,32,104,101,97, + 100,101,114,32,111,102,32,233,8,0,0,0,114,84,0,0, + 0,122,14,105,110,118,97,108,105,100,32,102,108,97,103,115, + 32,122,4,32,105,110,32,233,252,255,255,255,41,7,218,12, + 77,65,71,73,67,95,78,85,77,66,69,82,114,118,0,0, + 0,218,16,95,118,101,114,98,111,115,101,95,109,101,115,115, + 97,103,101,114,103,0,0,0,114,33,0,0,0,218,8,69, + 79,70,69,114,114,111,114,114,21,0,0,0,41,6,114,56, + 0,0,0,114,102,0,0,0,218,11,101,120,99,95,100,101, + 116,97,105,108,115,90,5,109,97,103,105,99,114,79,0,0, + 0,114,71,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,218,13,95,99,108,97,115,115,105,102,121, + 95,112,121,99,177,1,0,0,115,28,0,0,0,0,16,12, + 1,8,1,16,1,12,1,12,1,12,1,10,1,12,1,8, + 1,16,2,8,1,16,1,12,1,114,135,0,0,0,99,5, + 0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,67, + 0,0,0,115,112,0,0,0,116,0,124,0,100,1,100,2, + 133,2,25,0,131,1,124,1,100,3,64,0,107,3,114,58, + 100,4,124,3,155,2,157,2,125,5,116,1,160,2,100,5, + 124,5,161,2,1,0,116,3,124,5,102,1,124,4,142,1, + 130,1,124,2,100,6,107,9,114,108,116,0,124,0,100,2, + 100,7,133,2,25,0,131,1,124,2,100,3,64,0,107,3, + 114,108,116,3,100,4,124,3,155,2,157,2,102,1,124,4, + 142,1,130,1,100,6,83,0,41,8,97,7,2,0,0,86, + 97,108,105,100,97,116,101,32,97,32,112,121,99,32,97,103, + 97,105,110,115,116,32,116,104,101,32,115,111,117,114,99,101, + 32,108,97,115,116,45,109,111,100,105,102,105,101,100,32,116, + 105,109,101,46,10,10,32,32,32,32,42,100,97,116,97,42, + 32,105,115,32,116,104,101,32,99,111,110,116,101,110,116,115, + 32,111,102,32,116,104,101,32,112,121,99,32,102,105,108,101, + 46,32,40,79,110,108,121,32,116,104,101,32,102,105,114,115, + 116,32,49,54,32,98,121,116,101,115,32,97,114,101,10,32, + 32,32,32,114,101,113,117,105,114,101,100,46,41,10,10,32, + 32,32,32,42,115,111,117,114,99,101,95,109,116,105,109,101, + 42,32,105,115,32,116,104,101,32,108,97,115,116,32,109,111, + 100,105,102,105,101,100,32,116,105,109,101,115,116,97,109,112, + 32,111,102,32,116,104,101,32,115,111,117,114,99,101,32,102, + 105,108,101,46,10,10,32,32,32,32,42,115,111,117,114,99, + 101,95,115,105,122,101,42,32,105,115,32,78,111,110,101,32, + 111,114,32,116,104,101,32,115,105,122,101,32,111,102,32,116, + 104,101,32,115,111,117,114,99,101,32,102,105,108,101,32,105, + 110,32,98,121,116,101,115,46,10,10,32,32,32,32,42,110, + 97,109,101,42,32,105,115,32,116,104,101,32,110,97,109,101, + 32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,98, + 101,105,110,103,32,105,109,112,111,114,116,101,100,46,32,73, + 116,32,105,115,32,117,115,101,100,32,102,111,114,32,108,111, + 103,103,105,110,103,46,10,10,32,32,32,32,42,101,120,99, + 95,100,101,116,97,105,108,115,42,32,105,115,32,97,32,100, + 105,99,116,105,111,110,97,114,121,32,112,97,115,115,101,100, + 32,116,111,32,73,109,112,111,114,116,69,114,114,111,114,32, + 105,102,32,105,116,32,114,97,105,115,101,100,32,102,111,114, + 10,32,32,32,32,105,109,112,114,111,118,101,100,32,100,101, + 98,117,103,103,105,110,103,46,10,10,32,32,32,32,65,110, + 32,73,109,112,111,114,116,69,114,114,111,114,32,105,115,32, + 114,97,105,115,101,100,32,105,102,32,116,104,101,32,98,121, + 116,101,99,111,100,101,32,105,115,32,115,116,97,108,101,46, + 10,10,32,32,32,32,114,129,0,0,0,233,12,0,0,0, + 108,3,0,0,0,255,127,255,127,3,0,122,22,98,121,116, + 101,99,111,100,101,32,105,115,32,115,116,97,108,101,32,102, + 111,114,32,122,2,123,125,78,114,128,0,0,0,41,4,114, + 21,0,0,0,114,118,0,0,0,114,132,0,0,0,114,103, + 0,0,0,41,6,114,56,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,102,0,0,0,114,134,0,0,0,114, + 79,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,218,23,95,118,97,108,105,100,97,116,101,95,116, + 105,109,101,115,116,97,109,112,95,112,121,99,210,1,0,0, + 115,14,0,0,0,0,19,24,1,10,1,12,1,12,1,8, + 1,24,1,114,139,0,0,0,99,4,0,0,0,0,0,0, + 0,4,0,0,0,3,0,0,0,67,0,0,0,115,38,0, + 0,0,124,0,100,1,100,2,133,2,25,0,124,1,107,3, + 114,34,116,0,100,3,124,2,155,2,157,2,102,1,124,3, + 142,1,130,1,100,4,83,0,41,5,97,243,1,0,0,86, + 97,108,105,100,97,116,101,32,97,32,104,97,115,104,45,98, + 97,115,101,100,32,112,121,99,32,98,121,32,99,104,101,99, + 107,105,110,103,32,116,104,101,32,114,101,97,108,32,115,111, + 117,114,99,101,32,104,97,115,104,32,97,103,97,105,110,115, + 116,32,116,104,101,32,111,110,101,32,105,110,10,32,32,32, + 32,116,104,101,32,112,121,99,32,104,101,97,100,101,114,46, + 10,10,32,32,32,32,42,100,97,116,97,42,32,105,115,32, + 116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32, + 116,104,101,32,112,121,99,32,102,105,108,101,46,32,40,79, + 110,108,121,32,116,104,101,32,102,105,114,115,116,32,49,54, + 32,98,121,116,101,115,32,97,114,101,10,32,32,32,32,114, + 101,113,117,105,114,101,100,46,41,10,10,32,32,32,32,42, + 115,111,117,114,99,101,95,104,97,115,104,42,32,105,115,32, + 116,104,101,32,105,109,112,111,114,116,108,105,98,46,117,116, + 105,108,46,115,111,117,114,99,101,95,104,97,115,104,40,41, + 32,111,102,32,116,104,101,32,115,111,117,114,99,101,32,102, + 105,108,101,46,10,10,32,32,32,32,42,110,97,109,101,42, + 32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32, + 116,104,101,32,109,111,100,117,108,101,32,98,101,105,110,103, + 32,105,109,112,111,114,116,101,100,46,32,73,116,32,105,115, + 32,117,115,101,100,32,102,111,114,32,108,111,103,103,105,110, + 103,46,10,10,32,32,32,32,42,101,120,99,95,100,101,116, + 97,105,108,115,42,32,105,115,32,97,32,100,105,99,116,105, + 111,110,97,114,121,32,112,97,115,115,101,100,32,116,111,32, + 73,109,112,111,114,116,69,114,114,111,114,32,105,102,32,105, + 116,32,114,97,105,115,101,100,32,102,111,114,10,32,32,32, + 32,105,109,112,114,111,118,101,100,32,100,101,98,117,103,103, + 105,110,103,46,10,10,32,32,32,32,65,110,32,73,109,112, + 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, + 101,100,32,105,102,32,116,104,101,32,98,121,116,101,99,111, + 100,101,32,105,115,32,115,116,97,108,101,46,10,10,32,32, + 32,32,114,129,0,0,0,114,128,0,0,0,122,46,104,97, + 115,104,32,105,110,32,98,121,116,101,99,111,100,101,32,100, + 111,101,115,110,39,116,32,109,97,116,99,104,32,104,97,115, + 104,32,111,102,32,115,111,117,114,99,101,32,78,41,1,114, + 103,0,0,0,41,4,114,56,0,0,0,218,11,115,111,117, + 114,99,101,95,104,97,115,104,114,102,0,0,0,114,134,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,218,17,95,99,111,100,101,95,116,111,95,98,121,116,101, - 99,111,100,101,243,1,0,0,115,10,0,0,0,0,3,8, - 1,14,1,14,1,16,1,114,148,0,0,0,99,1,0,0, - 0,0,0,0,0,5,0,0,0,6,0,0,0,67,0,0, - 0,115,62,0,0,0,100,1,100,2,108,0,125,1,116,1, - 160,2,124,0,161,1,106,3,125,2,124,1,160,4,124,2, - 161,1,125,3,116,1,160,5,100,2,100,3,161,2,125,4, - 124,4,160,6,124,0,160,6,124,3,100,1,25,0,161,1, - 161,1,83,0,41,4,122,121,68,101,99,111,100,101,32,98, - 121,116,101,115,32,114,101,112,114,101,115,101,110,116,105,110, - 103,32,115,111,117,114,99,101,32,99,111,100,101,32,97,110, - 100,32,114,101,116,117,114,110,32,116,104,101,32,115,116,114, - 105,110,103,46,10,10,32,32,32,32,85,110,105,118,101,114, - 115,97,108,32,110,101,119,108,105,110,101,32,115,117,112,112, - 111,114,116,32,105,115,32,117,115,101,100,32,105,110,32,116, - 104,101,32,100,101,99,111,100,105,110,103,46,10,32,32,32, - 32,114,62,0,0,0,78,84,41,7,218,8,116,111,107,101, - 110,105,122,101,114,52,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,149,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,6,0,0,0,218,13,100,101,99,111,100,101,95,115, - 111,117,114,99,101,253,1,0,0,115,10,0,0,0,0,5, - 8,1,12,1,10,1,12,1,114,153,0,0,0,41,2,114, - 124,0,0,0,218,26,115,117,98,109,111,100,117,108,101,95, + 0,218,18,95,118,97,108,105,100,97,116,101,95,104,97,115, + 104,95,112,121,99,238,1,0,0,115,8,0,0,0,0,17, + 16,1,2,1,10,1,114,141,0,0,0,99,4,0,0,0, + 0,0,0,0,5,0,0,0,5,0,0,0,67,0,0,0, + 115,80,0,0,0,116,0,160,1,124,0,161,1,125,4,116, + 2,124,4,116,3,131,2,114,56,116,4,160,5,100,1,124, + 2,161,2,1,0,124,3,100,2,107,9,114,52,116,6,160, + 7,124,4,124,3,161,2,1,0,124,4,83,0,116,8,100, + 3,160,9,124,2,161,1,124,1,124,2,100,4,141,3,130, + 1,100,2,83,0,41,5,122,35,67,111,109,112,105,108,101, + 32,98,121,116,101,99,111,100,101,32,97,115,32,102,111,117, + 110,100,32,105,110,32,97,32,112,121,99,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,41,2,114, + 102,0,0,0,114,37,0,0,0,41,10,218,7,109,97,114, + 115,104,97,108,90,5,108,111,97,100,115,218,10,105,115,105, + 110,115,116,97,110,99,101,218,10,95,99,111,100,101,95,116, + 121,112,101,114,118,0,0,0,114,132,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,103,0,0,0,114,50,0,0,0,41, + 5,114,56,0,0,0,114,102,0,0,0,114,93,0,0,0, + 114,94,0,0,0,218,4,99,111,100,101,114,4,0,0,0, + 114,4,0,0,0,114,6,0,0,0,218,17,95,99,111,109, + 112,105,108,101,95,98,121,116,101,99,111,100,101,6,2,0, + 0,115,16,0,0,0,0,2,10,1,10,1,12,1,8,1, + 12,1,4,2,10,1,114,147,0,0,0,114,62,0,0,0, + 99,3,0,0,0,0,0,0,0,4,0,0,0,5,0,0, + 0,67,0,0,0,115,70,0,0,0,116,0,116,1,131,1, + 125,3,124,3,160,2,116,3,100,1,131,1,161,1,1,0, + 124,3,160,2,116,3,124,1,131,1,161,1,1,0,124,3, + 160,2,116,3,124,2,131,1,161,1,1,0,124,3,160,2, + 116,4,160,5,124,0,161,1,161,1,1,0,124,3,83,0, + 41,2,122,43,80,114,111,100,117,99,101,32,116,104,101,32, + 100,97,116,97,32,102,111,114,32,97,32,116,105,109,101,115, + 116,97,109,112,45,98,97,115,101,100,32,112,121,99,46,114, + 62,0,0,0,41,6,218,9,98,121,116,101,97,114,114,97, + 121,114,131,0,0,0,218,6,101,120,116,101,110,100,114,19, + 0,0,0,114,142,0,0,0,218,5,100,117,109,112,115,41, + 4,114,146,0,0,0,218,5,109,116,105,109,101,114,138,0, + 0,0,114,56,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,218,22,95,99,111,100,101,95,116,111, + 95,116,105,109,101,115,116,97,109,112,95,112,121,99,19,2, + 0,0,115,12,0,0,0,0,2,8,1,14,1,14,1,14, + 1,16,1,114,152,0,0,0,84,99,3,0,0,0,0,0, + 0,0,5,0,0,0,5,0,0,0,67,0,0,0,115,80, + 0,0,0,116,0,116,1,131,1,125,3,100,1,124,2,100, + 1,62,0,66,0,125,4,124,3,160,2,116,3,124,4,131, + 1,161,1,1,0,116,4,124,1,131,1,100,2,107,2,115, + 50,116,5,130,1,124,3,160,2,124,1,161,1,1,0,124, + 3,160,2,116,6,160,7,124,0,161,1,161,1,1,0,124, + 3,83,0,41,3,122,38,80,114,111,100,117,99,101,32,116, + 104,101,32,100,97,116,97,32,102,111,114,32,97,32,104,97, + 115,104,45,98,97,115,101,100,32,112,121,99,46,114,31,0, + 0,0,114,129,0,0,0,41,8,114,148,0,0,0,114,131, + 0,0,0,114,149,0,0,0,114,19,0,0,0,114,33,0, + 0,0,218,14,65,115,115,101,114,116,105,111,110,69,114,114, + 111,114,114,142,0,0,0,114,150,0,0,0,41,5,114,146, + 0,0,0,114,140,0,0,0,90,7,99,104,101,99,107,101, + 100,114,56,0,0,0,114,71,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,6,0,0,0,218,17,95,99,111,100, + 101,95,116,111,95,104,97,115,104,95,112,121,99,29,2,0, + 0,115,14,0,0,0,0,2,8,1,12,1,14,1,16,1, + 10,1,16,1,114,154,0,0,0,99,1,0,0,0,0,0, + 0,0,5,0,0,0,6,0,0,0,67,0,0,0,115,62, + 0,0,0,100,1,100,2,108,0,125,1,116,1,160,2,124, + 0,161,1,106,3,125,2,124,1,160,4,124,2,161,1,125, + 3,116,1,160,5,100,2,100,3,161,2,125,4,124,4,160, + 6,124,0,160,6,124,3,100,1,25,0,161,1,161,1,83, + 0,41,4,122,121,68,101,99,111,100,101,32,98,121,116,101, + 115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,115, + 111,117,114,99,101,32,99,111,100,101,32,97,110,100,32,114, + 101,116,117,114,110,32,116,104,101,32,115,116,114,105,110,103, + 46,10,10,32,32,32,32,85,110,105,118,101,114,115,97,108, + 32,110,101,119,108,105,110,101,32,115,117,112,112,111,114,116, + 32,105,115,32,117,115,101,100,32,105,110,32,116,104,101,32, + 100,101,99,111,100,105,110,103,46,10,32,32,32,32,114,62, + 0,0,0,78,84,41,7,218,8,116,111,107,101,110,105,122, + 101,114,52,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,155,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,6, + 0,0,0,218,13,100,101,99,111,100,101,95,115,111,117,114, + 99,101,40,2,0,0,115,10,0,0,0,0,5,8,1,12, + 1,10,1,12,1,114,159,0,0,0,41,2,114,124,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,18,1,0,0,124,1,100,1,107,8,114,60,100, + 2,125,1,116,0,124,2,100,3,131,2,114,70,121,14,124, + 2,160,1,124,0,161,1,125,1,87,0,113,70,4,0,116, + 2,107,10,114,56,1,0,1,0,1,0,89,0,113,70,88, + 0,110,10,116,3,160,4,124,1,161,1,125,1,116,5,106, + 6,124,0,124,2,124,1,100,4,141,3,125,4,100,5,124, + 4,95,7,124,2,100,1,107,8,114,156,120,54,116,8,131, + 0,68,0,93,40,92,2,125,5,125,6,124,1,160,9,116, + 10,124,6,131,1,161,1,114,108,124,5,124,0,124,1,131, + 2,125,2,124,2,124,4,95,11,80,0,113,108,87,0,100, + 1,83,0,124,3,116,12,107,8,114,222,116,0,124,2,100, + 6,131,2,114,228,121,14,124,2,160,13,124,0,161,1,125, + 7,87,0,110,20,4,0,116,2,107,10,114,208,1,0,1, + 0,1,0,89,0,113,228,88,0,124,7,114,228,103,0,124, + 4,95,14,110,6,124,3,124,4,95,14,124,4,106,14,103, + 0,107,2,144,1,114,14,124,1,144,1,114,14,116,15,124, + 1,131,1,100,7,25,0,125,8,124,4,106,14,160,16,124, + 8,161,1,1,0,124,4,83,0,41,8,97,61,1,0,0, + 82,101,116,117,114,110,32,97,32,109,111,100,117,108,101,32, + 115,112,101,99,32,98,97,115,101,100,32,111,110,32,97,32, + 102,105,108,101,32,108,111,99,97,116,105,111,110,46,10,10, + 32,32,32,32,84,111,32,105,110,100,105,99,97,116,101,32, + 116,104,97,116,32,116,104,101,32,109,111,100,117,108,101,32, + 105,115,32,97,32,112,97,99,107,97,103,101,44,32,115,101, + 116,10,32,32,32,32,115,117,98,109,111,100,117,108,101,95, 115,101,97,114,99,104,95,108,111,99,97,116,105,111,110,115, - 99,2,0,0,0,2,0,0,0,9,0,0,0,19,0,0, - 0,67,0,0,0,115,18,1,0,0,124,1,100,1,107,8, - 114,60,100,2,125,1,116,0,124,2,100,3,131,2,114,70, - 121,14,124,2,160,1,124,0,161,1,125,1,87,0,113,70, - 4,0,116,2,107,10,114,56,1,0,1,0,1,0,89,0, - 113,70,88,0,110,10,116,3,160,4,124,1,161,1,125,1, - 116,5,106,6,124,0,124,2,124,1,100,4,141,3,125,4, - 100,5,124,4,95,7,124,2,100,1,107,8,114,156,120,54, - 116,8,131,0,68,0,93,40,92,2,125,5,125,6,124,1, - 160,9,116,10,124,6,131,1,161,1,114,108,124,5,124,0, - 124,1,131,2,125,2,124,2,124,4,95,11,80,0,113,108, - 87,0,100,1,83,0,124,3,116,12,107,8,114,222,116,0, - 124,2,100,6,131,2,114,228,121,14,124,2,160,13,124,0, - 161,1,125,7,87,0,110,20,4,0,116,2,107,10,114,208, - 1,0,1,0,1,0,89,0,113,228,88,0,124,7,114,228, - 103,0,124,4,95,14,110,6,124,3,124,4,95,14,124,4, - 106,14,103,0,107,2,144,1,114,14,124,1,144,1,114,14, - 116,15,124,1,131,1,100,7,25,0,125,8,124,4,106,14, - 160,16,124,8,161,1,1,0,124,4,83,0,41,8,97,61, - 1,0,0,82,101,116,117,114,110,32,97,32,109,111,100,117, - 108,101,32,115,112,101,99,32,98,97,115,101,100,32,111,110, - 32,97,32,102,105,108,101,32,108,111,99,97,116,105,111,110, - 46,10,10,32,32,32,32,84,111,32,105,110,100,105,99,97, - 116,101,32,116,104,97,116,32,116,104,101,32,109,111,100,117, - 108,101,32,105,115,32,97,32,112,97,99,107,97,103,101,44, - 32,115,101,116,10,32,32,32,32,115,117,98,109,111,100,117, - 108,101,95,115,101,97,114,99,104,95,108,111,99,97,116,105, - 111,110,115,32,116,111,32,97,32,108,105,115,116,32,111,102, - 32,100,105,114,101,99,116,111,114,121,32,112,97,116,104,115, - 46,32,32,65,110,10,32,32,32,32,101,109,112,116,121,32, - 108,105,115,116,32,105,115,32,115,117,102,102,105,99,105,101, - 110,116,44,32,116,104,111,117,103,104,32,105,116,115,32,110, - 111,116,32,111,116,104,101,114,119,105,115,101,32,117,115,101, - 102,117,108,32,116,111,32,116,104,101,10,32,32,32,32,105, - 109,112,111,114,116,32,115,121,115,116,101,109,46,10,10,32, - 32,32,32,84,104,101,32,108,111,97,100,101,114,32,109,117, - 115,116,32,116,97,107,101,32,97,32,115,112,101,99,32,97, - 115,32,105,116,115,32,111,110,108,121,32,95,95,105,110,105, - 116,95,95,40,41,32,97,114,103,46,10,10,32,32,32,32, - 78,122,9,60,117,110,107,110,111,119,110,62,218,12,103,101, - 116,95,102,105,108,101,110,97,109,101,41,1,218,6,111,114, - 105,103,105,110,84,218,10,105,115,95,112,97,99,107,97,103, - 101,114,62,0,0,0,41,17,114,112,0,0,0,114,155,0, - 0,0,114,103,0,0,0,114,3,0,0,0,114,67,0,0, - 0,114,118,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,96, - 0,0,0,114,97,0,0,0,114,124,0,0,0,218,9,95, - 80,79,80,85,76,65,84,69,114,157,0,0,0,114,154,0, - 0,0,114,40,0,0,0,218,6,97,112,112,101,110,100,41, - 9,114,102,0,0,0,90,8,108,111,99,97,116,105,111,110, - 114,124,0,0,0,114,154,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,157,0,0,0,90,7,100, - 105,114,110,97,109,101,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,23,115,112,101,99,95,102,114,111,109, - 95,102,105,108,101,95,108,111,99,97,116,105,111,110,14,2, - 0,0,115,62,0,0,0,0,12,8,4,4,1,10,2,2, - 1,14,1,14,1,8,2,10,8,16,1,6,3,8,1,16, - 1,14,1,10,1,6,1,6,2,4,3,8,2,10,1,2, - 1,14,1,14,1,6,2,4,1,8,2,6,1,12,1,6, - 1,12,1,12,2,114,165,0,0,0,99,0,0,0,0,0, - 0,0,0,0,0,0,0,4,0,0,0,64,0,0,0,115, - 80,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, - 100,2,90,4,100,3,90,5,100,4,90,6,101,7,100,5, - 100,6,132,0,131,1,90,8,101,7,100,7,100,8,132,0, - 131,1,90,9,101,7,100,14,100,10,100,11,132,1,131,1, - 90,10,101,7,100,15,100,12,100,13,132,1,131,1,90,11, - 100,9,83,0,41,16,218,21,87,105,110,100,111,119,115,82, - 101,103,105,115,116,114,121,70,105,110,100,101,114,122,62,77, - 101,116,97,32,112,97,116,104,32,102,105,110,100,101,114,32, - 102,111,114,32,109,111,100,117,108,101,115,32,100,101,99,108, - 97,114,101,100,32,105,110,32,116,104,101,32,87,105,110,100, - 111,119,115,32,114,101,103,105,115,116,114,121,46,122,59,83, - 111,102,116,119,97,114,101,92,80,121,116,104,111,110,92,80, - 121,116,104,111,110,67,111,114,101,92,123,115,121,115,95,118, - 101,114,115,105,111,110,125,92,77,111,100,117,108,101,115,92, - 123,102,117,108,108,110,97,109,101,125,122,65,83,111,102,116, + 32,116,111,32,97,32,108,105,115,116,32,111,102,32,100,105, + 114,101,99,116,111,114,121,32,112,97,116,104,115,46,32,32, + 65,110,10,32,32,32,32,101,109,112,116,121,32,108,105,115, + 116,32,105,115,32,115,117,102,102,105,99,105,101,110,116,44, + 32,116,104,111,117,103,104,32,105,116,115,32,110,111,116,32, + 111,116,104,101,114,119,105,115,101,32,117,115,101,102,117,108, + 32,116,111,32,116,104,101,10,32,32,32,32,105,109,112,111, + 114,116,32,115,121,115,116,101,109,46,10,10,32,32,32,32, + 84,104,101,32,108,111,97,100,101,114,32,109,117,115,116,32, + 116,97,107,101,32,97,32,115,112,101,99,32,97,115,32,105, + 116,115,32,111,110,108,121,32,95,95,105,110,105,116,95,95, + 40,41,32,97,114,103,46,10,10,32,32,32,32,78,122,9, + 60,117,110,107,110,111,119,110,62,218,12,103,101,116,95,102, + 105,108,101,110,97,109,101,41,1,218,6,111,114,105,103,105, + 110,84,218,10,105,115,95,112,97,99,107,97,103,101,114,62, + 0,0,0,41,17,114,112,0,0,0,114,161,0,0,0,114, + 103,0,0,0,114,3,0,0,0,114,67,0,0,0,114,118, + 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,96,0,0,0, + 114,97,0,0,0,114,124,0,0,0,218,9,95,80,79,80, + 85,76,65,84,69,114,163,0,0,0,114,160,0,0,0,114, + 40,0,0,0,218,6,97,112,112,101,110,100,41,9,114,102, + 0,0,0,90,8,108,111,99,97,116,105,111,110,114,124,0, + 0,0,114,160,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,163,0,0,0,90,7,100,105,114,110, + 97,109,101,114,4,0,0,0,114,4,0,0,0,114,6,0, + 0,0,218,23,115,112,101,99,95,102,114,111,109,95,102,105, + 108,101,95,108,111,99,97,116,105,111,110,57,2,0,0,115, + 62,0,0,0,0,12,8,4,4,1,10,2,2,1,14,1, + 14,1,8,2,10,8,16,1,6,3,8,1,16,1,14,1, + 10,1,6,1,6,2,4,3,8,2,10,1,2,1,14,1, + 14,1,6,2,4,1,8,2,6,1,12,1,6,1,12,1, + 12,2,114,171,0,0,0,99,0,0,0,0,0,0,0,0, + 0,0,0,0,4,0,0,0,64,0,0,0,115,80,0,0, + 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,90, + 4,100,3,90,5,100,4,90,6,101,7,100,5,100,6,132, + 0,131,1,90,8,101,7,100,7,100,8,132,0,131,1,90, + 9,101,7,100,14,100,10,100,11,132,1,131,1,90,10,101, + 7,100,15,100,12,100,13,132,1,131,1,90,11,100,9,83, + 0,41,16,218,21,87,105,110,100,111,119,115,82,101,103,105, + 115,116,114,121,70,105,110,100,101,114,122,62,77,101,116,97, + 32,112,97,116,104,32,102,105,110,100,101,114,32,102,111,114, + 32,109,111,100,117,108,101,115,32,100,101,99,108,97,114,101, + 100,32,105,110,32,116,104,101,32,87,105,110,100,111,119,115, + 32,114,101,103,105,115,116,114,121,46,122,59,83,111,102,116, 119,97,114,101,92,80,121,116,104,111,110,92,80,121,116,104, 111,110,67,111,114,101,92,123,115,121,115,95,118,101,114,115, 105,111,110,125,92,77,111,100,117,108,101,115,92,123,102,117, - 108,108,110,97,109,101,125,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,50,0,0,0,121,14,116,0,160,1,116,0, - 106,2,124,1,161,2,83,0,4,0,116,3,107,10,114,44, - 1,0,1,0,1,0,116,0,160,1,116,0,106,4,124,1, - 161,2,83,0,88,0,100,0,83,0,41,1,78,41,5,218, - 7,95,119,105,110,114,101,103,90,7,79,112,101,110,75,101, - 121,90,17,72,75,69,89,95,67,85,82,82,69,78,84,95, - 85,83,69,82,114,42,0,0,0,90,18,72,75,69,89,95, - 76,79,67,65,76,95,77,65,67,72,73,78,69,41,2,218, - 3,99,108,115,114,5,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,218,14,95,111,112,101,110,95, - 114,101,103,105,115,116,114,121,94,2,0,0,115,8,0,0, - 0,0,2,2,1,14,1,14,1,122,36,87,105,110,100,111, - 119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,114, - 46,95,111,112,101,110,95,114,101,103,105,115,116,114,121,99, - 2,0,0,0,0,0,0,0,6,0,0,0,17,0,0,0, - 67,0,0,0,115,112,0,0,0,124,0,106,0,114,14,124, - 0,106,1,125,2,110,6,124,0,106,2,125,2,124,2,106, - 3,124,1,100,1,116,4,106,5,100,0,100,2,133,2,25, - 0,22,0,100,3,141,2,125,3,121,38,124,0,160,6,124, - 3,161,1,143,18,125,4,116,7,160,8,124,4,100,4,161, - 2,125,5,87,0,100,0,81,0,82,0,88,0,87,0,110, - 20,4,0,116,9,107,10,114,106,1,0,1,0,1,0,100, - 0,83,0,88,0,124,5,83,0,41,5,78,122,5,37,100, - 46,37,100,114,59,0,0,0,41,2,114,123,0,0,0,90, - 11,115,121,115,95,118,101,114,115,105,111,110,114,32,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,50,0,0,0,114,8,0,0,0,218,12,118,101, - 114,115,105,111,110,95,105,110,102,111,114,169,0,0,0,114, - 167,0,0,0,90,10,81,117,101,114,121,86,97,108,117,101, - 114,42,0,0,0,41,6,114,168,0,0,0,114,123,0,0, - 0,90,12,114,101,103,105,115,116,114,121,95,107,101,121,114, - 5,0,0,0,90,4,104,107,101,121,218,8,102,105,108,101, - 112,97,116,104,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,218,16,95,115,101,97,114,99,104,95,114,101,103, - 105,115,116,114,121,101,2,0,0,115,22,0,0,0,0,2, - 6,1,8,2,6,1,6,1,22,1,2,1,12,1,26,1, - 14,1,6,1,122,38,87,105,110,100,111,119,115,82,101,103, - 105,115,116,114,121,70,105,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,120,0,0,0,124,0,160,0,124,1,161,1,125, - 4,124,4,100,0,107,8,114,22,100,0,83,0,121,12,116, - 1,124,4,131,1,1,0,87,0,110,20,4,0,116,2,107, - 10,114,54,1,0,1,0,1,0,100,0,83,0,88,0,120, - 58,116,3,131,0,68,0,93,48,92,2,125,5,125,6,124, - 4,160,4,116,5,124,6,131,1,161,1,114,64,116,6,106, - 7,124,1,124,5,124,1,124,4,131,2,124,4,100,1,141, - 3,125,7,124,7,83,0,113,64,87,0,100,0,83,0,41, - 2,78,41,1,114,156,0,0,0,41,8,114,175,0,0,0, - 114,41,0,0,0,114,42,0,0,0,114,159,0,0,0,114, - 96,0,0,0,114,97,0,0,0,114,118,0,0,0,218,16, - 115,112,101,99,95,102,114,111,109,95,108,111,97,100,101,114, - 41,8,114,168,0,0,0,114,123,0,0,0,114,37,0,0, - 0,218,6,116,97,114,103,101,116,114,174,0,0,0,114,124, - 0,0,0,114,164,0,0,0,114,162,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,218,9,102,105, - 110,100,95,115,112,101,99,116,2,0,0,115,26,0,0,0, - 0,2,10,1,8,1,4,1,2,1,12,1,14,1,6,1, - 16,1,14,1,6,1,8,1,8,1,122,31,87,105,110,100, - 111,119,115,82,101,103,105,115,116,114,121,70,105,110,100,101, - 114,46,102,105,110,100,95,115,112,101,99,99,3,0,0,0, - 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, - 115,34,0,0,0,124,0,160,0,124,1,124,2,161,2,125, - 3,124,3,100,1,107,9,114,26,124,3,106,1,83,0,100, - 1,83,0,100,1,83,0,41,2,122,108,70,105,110,100,32, - 109,111,100,117,108,101,32,110,97,109,101,100,32,105,110,32, - 116,104,101,32,114,101,103,105,115,116,114,121,46,10,10,32, - 32,32,32,32,32,32,32,84,104,105,115,32,109,101,116,104, - 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, - 46,32,32,85,115,101,32,101,120,101,99,95,109,111,100,117, - 108,101,40,41,32,105,110,115,116,101,97,100,46,10,10,32, - 32,32,32,32,32,32,32,78,41,2,114,178,0,0,0,114, - 124,0,0,0,41,4,114,168,0,0,0,114,123,0,0,0, - 114,37,0,0,0,114,162,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,218,11,102,105,110,100,95, - 109,111,100,117,108,101,132,2,0,0,115,8,0,0,0,0, - 7,12,1,8,1,6,2,122,33,87,105,110,100,111,119,115, + 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,50,0,0,0,121,14,116,0,160,1,116,0,106,2,124, + 1,161,2,83,0,4,0,116,3,107,10,114,44,1,0,1, + 0,1,0,116,0,160,1,116,0,106,4,124,1,161,2,83, + 0,88,0,100,0,83,0,41,1,78,41,5,218,7,95,119, + 105,110,114,101,103,90,7,79,112,101,110,75,101,121,90,17, + 72,75,69,89,95,67,85,82,82,69,78,84,95,85,83,69, + 82,114,42,0,0,0,90,18,72,75,69,89,95,76,79,67, + 65,76,95,77,65,67,72,73,78,69,41,2,218,3,99,108, + 115,114,5,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,218,14,95,111,112,101,110,95,114,101,103, + 105,115,116,114,121,137,2,0,0,115,8,0,0,0,0,2, + 2,1,14,1,14,1,122,36,87,105,110,100,111,119,115,82, + 101,103,105,115,116,114,121,70,105,110,100,101,114,46,95,111, + 112,101,110,95,114,101,103,105,115,116,114,121,99,2,0,0, + 0,0,0,0,0,6,0,0,0,17,0,0,0,67,0,0, + 0,115,112,0,0,0,124,0,106,0,114,14,124,0,106,1, + 125,2,110,6,124,0,106,2,125,2,124,2,106,3,124,1, + 100,1,116,4,106,5,100,0,100,2,133,2,25,0,22,0, + 100,3,141,2,125,3,121,38,124,0,160,6,124,3,161,1, + 143,18,125,4,116,7,160,8,124,4,100,4,161,2,125,5, + 87,0,100,0,81,0,82,0,88,0,87,0,110,20,4,0, + 116,9,107,10,114,106,1,0,1,0,1,0,100,0,83,0, + 88,0,124,5,83,0,41,5,78,122,5,37,100,46,37,100, + 114,59,0,0,0,41,2,114,123,0,0,0,90,11,115,121, + 115,95,118,101,114,115,105,111,110,114,32,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, + 50,0,0,0,114,8,0,0,0,218,12,118,101,114,115,105, + 111,110,95,105,110,102,111,114,175,0,0,0,114,173,0,0, + 0,90,10,81,117,101,114,121,86,97,108,117,101,114,42,0, + 0,0,41,6,114,174,0,0,0,114,123,0,0,0,90,12, + 114,101,103,105,115,116,114,121,95,107,101,121,114,5,0,0, + 0,90,4,104,107,101,121,218,8,102,105,108,101,112,97,116, + 104,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, + 218,16,95,115,101,97,114,99,104,95,114,101,103,105,115,116, + 114,121,144,2,0,0,115,22,0,0,0,0,2,6,1,8, + 2,6,1,6,1,22,1,2,1,12,1,26,1,14,1,6, + 1,122,38,87,105,110,100,111,119,115,82,101,103,105,115,116, + 114,121,70,105,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, + 120,0,0,0,124,0,160,0,124,1,161,1,125,4,124,4, + 100,0,107,8,114,22,100,0,83,0,121,12,116,1,124,4, + 131,1,1,0,87,0,110,20,4,0,116,2,107,10,114,54, + 1,0,1,0,1,0,100,0,83,0,88,0,120,58,116,3, + 131,0,68,0,93,48,92,2,125,5,125,6,124,4,160,4, + 116,5,124,6,131,1,161,1,114,64,116,6,106,7,124,1, + 124,5,124,1,124,4,131,2,124,4,100,1,141,3,125,7, + 124,7,83,0,113,64,87,0,100,0,83,0,41,2,78,41, + 1,114,162,0,0,0,41,8,114,181,0,0,0,114,41,0, + 0,0,114,42,0,0,0,114,165,0,0,0,114,96,0,0, + 0,114,97,0,0,0,114,118,0,0,0,218,16,115,112,101, + 99,95,102,114,111,109,95,108,111,97,100,101,114,41,8,114, + 174,0,0,0,114,123,0,0,0,114,37,0,0,0,218,6, + 116,97,114,103,101,116,114,180,0,0,0,114,124,0,0,0, + 114,170,0,0,0,114,168,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,218,9,102,105,110,100,95, + 115,112,101,99,159,2,0,0,115,26,0,0,0,0,2,10, + 1,8,1,4,1,2,1,12,1,14,1,6,1,16,1,14, + 1,6,1,8,1,8,1,122,31,87,105,110,100,111,119,115, 82,101,103,105,115,116,114,121,70,105,110,100,101,114,46,102, - 105,110,100,95,109,111,100,117,108,101,41,2,78,78,41,1, - 78,41,12,114,109,0,0,0,114,108,0,0,0,114,110,0, - 0,0,114,111,0,0,0,114,172,0,0,0,114,171,0,0, - 0,114,170,0,0,0,218,11,99,108,97,115,115,109,101,116, - 104,111,100,114,169,0,0,0,114,175,0,0,0,114,178,0, - 0,0,114,179,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,114,166,0,0,0, - 82,2,0,0,115,18,0,0,0,12,5,4,3,4,2,4, - 2,12,7,12,15,2,1,12,15,2,1,114,166,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,64,0,0,0,115,48,0,0,0,101,0,90,1,100,0, - 90,2,100,1,90,3,100,2,100,3,132,0,90,4,100,4, - 100,5,132,0,90,5,100,6,100,7,132,0,90,6,100,8, - 100,9,132,0,90,7,100,10,83,0,41,11,218,13,95,76, - 111,97,100,101,114,66,97,115,105,99,115,122,83,66,97,115, - 101,32,99,108,97,115,115,32,111,102,32,99,111,109,109,111, - 110,32,99,111,100,101,32,110,101,101,100,101,100,32,98,121, - 32,98,111,116,104,32,83,111,117,114,99,101,76,111,97,100, - 101,114,32,97,110,100,10,32,32,32,32,83,111,117,114,99, - 101,108,101,115,115,70,105,108,101,76,111,97,100,101,114,46, - 99,2,0,0,0,0,0,0,0,5,0,0,0,4,0,0, - 0,67,0,0,0,115,64,0,0,0,116,0,124,0,160,1, - 124,1,161,1,131,1,100,1,25,0,125,2,124,2,160,2, - 100,2,100,1,161,2,100,3,25,0,125,3,124,1,160,3, - 100,2,161,1,100,4,25,0,125,4,124,3,100,5,107,2, - 111,62,124,4,100,5,107,3,83,0,41,6,122,141,67,111, - 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, - 97,116,105,111,110,32,111,102,32,73,110,115,112,101,99,116, - 76,111,97,100,101,114,46,105,115,95,112,97,99,107,97,103, - 101,32,98,121,32,99,104,101,99,107,105,110,103,32,105,102, - 10,32,32,32,32,32,32,32,32,116,104,101,32,112,97,116, - 104,32,114,101,116,117,114,110,101,100,32,98,121,32,103,101, - 116,95,102,105,108,101,110,97,109,101,32,104,97,115,32,97, - 32,102,105,108,101,110,97,109,101,32,111,102,32,39,95,95, - 105,110,105,116,95,95,46,112,121,39,46,114,31,0,0,0, - 114,61,0,0,0,114,62,0,0,0,114,59,0,0,0,218, - 8,95,95,105,110,105,116,95,95,41,4,114,40,0,0,0, - 114,155,0,0,0,114,36,0,0,0,114,34,0,0,0,41, - 5,114,104,0,0,0,114,123,0,0,0,114,98,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,6,0,0,0,114,157,0,0,0,151,2, - 0,0,115,8,0,0,0,0,3,18,1,16,1,14,1,122, - 24,95,76,111,97,100,101,114,66,97,115,105,99,115,46,105, - 115,95,112,97,99,107,97,103,101,99,2,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, - 0,0,0,100,1,83,0,41,2,122,42,85,115,101,32,100, - 101,102,97,117,108,116,32,115,101,109,97,110,116,105,99,115, - 32,102,111,114,32,109,111,100,117,108,101,32,99,114,101,97, - 116,105,111,110,46,78,114,4,0,0,0,41,2,114,104,0, - 0,0,114,162,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,13,99,114,101,97,116,101,95,109, - 111,100,117,108,101,159,2,0,0,115,0,0,0,0,122,27, - 95,76,111,97,100,101,114,66,97,115,105,99,115,46,99,114, - 101,97,116,101,95,109,111,100,117,108,101,99,2,0,0,0, - 0,0,0,0,3,0,0,0,5,0,0,0,67,0,0,0, - 115,56,0,0,0,124,0,160,0,124,1,106,1,161,1,125, - 2,124,2,100,1,107,8,114,36,116,2,100,2,160,3,124, - 1,106,1,161,1,131,1,130,1,116,4,160,5,116,6,124, - 2,124,1,106,7,161,3,1,0,100,1,83,0,41,3,122, - 19,69,120,101,99,117,116,101,32,116,104,101,32,109,111,100, - 117,108,101,46,78,122,52,99,97,110,110,111,116,32,108,111, - 97,100,32,109,111,100,117,108,101,32,123,33,114,125,32,119, - 104,101,110,32,103,101,116,95,99,111,100,101,40,41,32,114, - 101,116,117,114,110,115,32,78,111,110,101,41,8,218,8,103, - 101,116,95,99,111,100,101,114,109,0,0,0,114,103,0,0, - 0,114,50,0,0,0,114,118,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,115,0,0, - 0,41,3,114,104,0,0,0,218,6,109,111,100,117,108,101, - 114,144,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108, - 101,162,2,0,0,115,10,0,0,0,0,2,12,1,8,1, - 6,1,10,1,122,25,95,76,111,97,100,101,114,66,97,115, - 105,99,115,46,101,120,101,99,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 67,0,0,0,115,12,0,0,0,116,0,160,1,124,0,124, - 1,161,2,83,0,41,1,122,26,84,104,105,115,32,109,111, - 100,117,108,101,32,105,115,32,100,101,112,114,101,99,97,116, - 101,100,46,41,2,114,118,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, - 104,0,0,0,114,123,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,218,11,108,111,97,100,95,109, - 111,100,117,108,101,170,2,0,0,115,2,0,0,0,0,2, - 122,25,95,76,111,97,100,101,114,66,97,115,105,99,115,46, - 108,111,97,100,95,109,111,100,117,108,101,78,41,8,114,109, - 0,0,0,114,108,0,0,0,114,110,0,0,0,114,111,0, - 0,0,114,157,0,0,0,114,183,0,0,0,114,188,0,0, - 0,114,190,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,114,181,0,0,0,146, - 2,0,0,115,8,0,0,0,12,5,8,8,8,3,8,8, - 114,181,0,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,3,0,0,0,64,0,0,0,115,74,0,0,0,101, - 0,90,1,100,0,90,2,100,1,100,2,132,0,90,3,100, - 3,100,4,132,0,90,4,100,5,100,6,132,0,90,5,100, - 7,100,8,132,0,90,6,100,9,100,10,132,0,90,7,100, - 18,100,12,156,1,100,13,100,14,132,2,90,8,100,15,100, - 16,132,0,90,9,100,17,83,0,41,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,8, - 0,0,0,116,0,130,1,100,1,83,0,41,2,122,178,79, - 112,116,105,111,110,97,108,32,109,101,116,104,111,100,32,116, - 104,97,116,32,114,101,116,117,114,110,115,32,116,104,101,32, - 109,111,100,105,102,105,99,97,116,105,111,110,32,116,105,109, - 101,32,40,97,110,32,105,110,116,41,32,102,111,114,32,116, - 104,101,10,32,32,32,32,32,32,32,32,115,112,101,99,105, - 102,105,101,100,32,112,97,116,104,44,32,119,104,101,114,101, - 32,112,97,116,104,32,105,115,32,97,32,115,116,114,46,10, - 10,32,32,32,32,32,32,32,32,82,97,105,115,101,115,32, - 79,83,69,114,114,111,114,32,119,104,101,110,32,116,104,101, - 32,112,97,116,104,32,99,97,110,110,111,116,32,98,101,32, - 104,97,110,100,108,101,100,46,10,32,32,32,32,32,32,32, - 32,78,41,1,114,42,0,0,0,41,2,114,104,0,0,0, - 114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,10,112,97,116,104,95,109,116,105,109,101, - 177,2,0,0,115,2,0,0,0,0,6,122,23,83,111,117, - 114,99,101,76,111,97,100,101,114,46,112,97,116,104,95,109, - 116,105,109,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,4,0,0,0,67,0,0,0,115,14,0,0,0,100,1, - 124,0,160,0,124,1,161,1,105,1,83,0,41,2,97,170, - 1,0,0,79,112,116,105,111,110,97,108,32,109,101,116,104, - 111,100,32,114,101,116,117,114,110,105,110,103,32,97,32,109, - 101,116,97,100,97,116,97,32,100,105,99,116,32,102,111,114, - 32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,112, - 97,116,104,10,32,32,32,32,32,32,32,32,116,111,32,98, - 121,32,116,104,101,32,112,97,116,104,32,40,115,116,114,41, - 46,10,32,32,32,32,32,32,32,32,80,111,115,115,105,98, - 108,101,32,107,101,121,115,58,10,32,32,32,32,32,32,32, - 32,45,32,39,109,116,105,109,101,39,32,40,109,97,110,100, - 97,116,111,114,121,41,32,105,115,32,116,104,101,32,110,117, - 109,101,114,105,99,32,116,105,109,101,115,116,97,109,112,32, - 111,102,32,108,97,115,116,32,115,111,117,114,99,101,10,32, - 32,32,32,32,32,32,32,32,32,99,111,100,101,32,109,111, - 100,105,102,105,99,97,116,105,111,110,59,10,32,32,32,32, - 32,32,32,32,45,32,39,115,105,122,101,39,32,40,111,112, - 116,105,111,110,97,108,41,32,105,115,32,116,104,101,32,115, - 105,122,101,32,105,110,32,98,121,116,101,115,32,111,102,32, - 116,104,101,32,115,111,117,114,99,101,32,99,111,100,101,46, - 10,10,32,32,32,32,32,32,32,32,73,109,112,108,101,109, - 101,110,116,105,110,103,32,116,104,105,115,32,109,101,116,104, - 111,100,32,97,108,108,111,119,115,32,116,104,101,32,108,111, - 97,100,101,114,32,116,111,32,114,101,97,100,32,98,121,116, - 101,99,111,100,101,32,102,105,108,101,115,46,10,32,32,32, - 32,32,32,32,32,82,97,105,115,101,115,32,79,83,69,114, - 114,111,114,32,119,104,101,110,32,116,104,101,32,112,97,116, - 104,32,99,97,110,110,111,116,32,98,101,32,104,97,110,100, - 108,101,100,46,10,32,32,32,32,32,32,32,32,114,130,0, - 0,0,41,1,114,192,0,0,0,41,2,114,104,0,0,0, - 114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,10,112,97,116,104,95,115,116,97,116,115, - 185,2,0,0,115,2,0,0,0,0,11,122,23,83,111,117, - 114,99,101,76,111,97,100,101,114,46,112,97,116,104,95,115, - 116,97,116,115,99,4,0,0,0,0,0,0,0,4,0,0, - 0,4,0,0,0,67,0,0,0,115,12,0,0,0,124,0, - 160,0,124,2,124,3,161,2,83,0,41,1,122,228,79,112, - 116,105,111,110,97,108,32,109,101,116,104,111,100,32,119,104, - 105,99,104,32,119,114,105,116,101,115,32,100,97,116,97,32, - 40,98,121,116,101,115,41,32,116,111,32,97,32,102,105,108, - 101,32,112,97,116,104,32,40,97,32,115,116,114,41,46,10, - 10,32,32,32,32,32,32,32,32,73,109,112,108,101,109,101, - 110,116,105,110,103,32,116,104,105,115,32,109,101,116,104,111, - 100,32,97,108,108,111,119,115,32,102,111,114,32,116,104,101, - 32,119,114,105,116,105,110,103,32,111,102,32,98,121,116,101, - 99,111,100,101,32,102,105,108,101,115,46,10,10,32,32,32, - 32,32,32,32,32,84,104,101,32,115,111,117,114,99,101,32, - 112,97,116,104,32,105,115,32,110,101,101,100,101,100,32,105, - 110,32,111,114,100,101,114,32,116,111,32,99,111,114,114,101, - 99,116,108,121,32,116,114,97,110,115,102,101,114,32,112,101, - 114,109,105,115,115,105,111,110,115,10,32,32,32,32,32,32, - 32,32,41,1,218,8,115,101,116,95,100,97,116,97,41,4, - 114,104,0,0,0,114,94,0,0,0,90,10,99,97,99,104, - 101,95,112,97,116,104,114,56,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,218,15,95,99,97,99, - 104,101,95,98,121,116,101,99,111,100,101,198,2,0,0,115, - 2,0,0,0,0,8,122,28,83,111,117,114,99,101,76,111, - 97,100,101,114,46,95,99,97,99,104,101,95,98,121,116,101, - 99,111,100,101,99,3,0,0,0,0,0,0,0,3,0,0, - 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, - 83,0,41,2,122,150,79,112,116,105,111,110,97,108,32,109, - 101,116,104,111,100,32,119,104,105,99,104,32,119,114,105,116, - 101,115,32,100,97,116,97,32,40,98,121,116,101,115,41,32, - 116,111,32,97,32,102,105,108,101,32,112,97,116,104,32,40, - 97,32,115,116,114,41,46,10,10,32,32,32,32,32,32,32, - 32,73,109,112,108,101,109,101,110,116,105,110,103,32,116,104, - 105,115,32,109,101,116,104,111,100,32,97,108,108,111,119,115, - 32,102,111,114,32,116,104,101,32,119,114,105,116,105,110,103, - 32,111,102,32,98,121,116,101,99,111,100,101,32,102,105,108, - 101,115,46,10,32,32,32,32,32,32,32,32,78,114,4,0, - 0,0,41,3,114,104,0,0,0,114,37,0,0,0,114,56, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,114,194,0,0,0,208,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,82,0,0, - 0,124,0,160,0,124,1,161,1,125,2,121,14,124,0,160, - 1,124,2,161,1,125,3,87,0,110,48,4,0,116,2,107, - 10,114,72,1,0,125,4,1,0,122,20,116,3,100,1,124, - 1,100,2,141,2,124,4,130,2,87,0,89,0,100,3,100, - 3,125,4,126,4,88,0,110,2,88,0,116,4,124,3,131, - 1,83,0,41,4,122,52,67,111,110,99,114,101,116,101,32, - 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111, - 102,32,73,110,115,112,101,99,116,76,111,97,100,101,114,46, - 103,101,116,95,115,111,117,114,99,101,46,122,39,115,111,117, - 114,99,101,32,110,111,116,32,97,118,97,105,108,97,98,108, - 101,32,116,104,114,111,117,103,104,32,103,101,116,95,100,97, - 116,97,40,41,41,1,114,102,0,0,0,78,41,5,114,155, - 0,0,0,218,8,103,101,116,95,100,97,116,97,114,42,0, - 0,0,114,103,0,0,0,114,153,0,0,0,41,5,114,104, - 0,0,0,114,123,0,0,0,114,37,0,0,0,114,151,0, - 0,0,218,3,101,120,99,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,10,103,101,116,95,115,111,117,114, - 99,101,215,2,0,0,115,14,0,0,0,0,2,10,1,2, - 1,14,1,16,1,4,1,28,1,122,23,83,111,117,114,99, - 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, - 99,101,114,31,0,0,0,41,1,218,9,95,111,112,116,105, - 109,105,122,101,99,3,0,0,0,1,0,0,0,4,0,0, - 0,8,0,0,0,67,0,0,0,115,22,0,0,0,116,0, - 106,1,116,2,124,1,124,2,100,1,100,2,124,3,100,3, - 141,6,83,0,41,4,122,130,82,101,116,117,114,110,32,116, - 104,101,32,99,111,100,101,32,111,98,106,101,99,116,32,99, - 111,109,112,105,108,101,100,32,102,114,111,109,32,115,111,117, - 114,99,101,46,10,10,32,32,32,32,32,32,32,32,84,104, - 101,32,39,100,97,116,97,39,32,97,114,103,117,109,101,110, - 116,32,99,97,110,32,98,101,32,97,110,121,32,111,98,106, - 101,99,116,32,116,121,112,101,32,116,104,97,116,32,99,111, - 109,112,105,108,101,40,41,32,115,117,112,112,111,114,116,115, - 46,10,32,32,32,32,32,32,32,32,114,186,0,0,0,84, - 41,2,218,12,100,111,110,116,95,105,110,104,101,114,105,116, - 114,72,0,0,0,41,3,114,118,0,0,0,114,185,0,0, - 0,218,7,99,111,109,112,105,108,101,41,4,114,104,0,0, - 0,114,56,0,0,0,114,37,0,0,0,114,199,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218, - 14,115,111,117,114,99,101,95,116,111,95,99,111,100,101,225, - 2,0,0,115,4,0,0,0,0,5,12,1,122,27,83,111, - 117,114,99,101,76,111,97,100,101,114,46,115,111,117,114,99, - 101,95,116,111,95,99,111,100,101,99,2,0,0,0,0,0, - 0,0,10,0,0,0,43,0,0,0,67,0,0,0,115,92, - 1,0,0,124,0,160,0,124,1,161,1,125,2,100,1,125, - 3,121,12,116,1,124,2,131,1,125,4,87,0,110,24,4, - 0,116,2,107,10,114,50,1,0,1,0,1,0,100,1,125, - 4,89,0,110,162,88,0,121,14,124,0,160,3,124,2,161, - 1,125,5,87,0,110,20,4,0,116,4,107,10,114,86,1, - 0,1,0,1,0,89,0,110,126,88,0,116,5,124,5,100, - 2,25,0,131,1,125,3,121,14,124,0,160,6,124,4,161, - 1,125,6,87,0,110,20,4,0,116,4,107,10,114,134,1, - 0,1,0,1,0,89,0,110,78,88,0,121,20,116,7,124, - 6,124,5,124,1,124,4,100,3,141,4,125,7,87,0,110, - 24,4,0,116,8,116,9,102,2,107,10,114,180,1,0,1, - 0,1,0,89,0,110,32,88,0,116,10,160,11,100,4,124, - 4,124,2,161,3,1,0,116,12,124,7,124,1,124,4,124, - 2,100,5,141,4,83,0,124,0,160,6,124,2,161,1,125, - 8,124,0,160,13,124,8,124,2,161,2,125,9,116,10,160, - 11,100,6,124,2,161,2,1,0,116,14,106,15,144,1,115, - 88,124,4,100,1,107,9,144,1,114,88,124,3,100,1,107, - 9,144,1,114,88,116,16,124,9,124,3,116,17,124,8,131, - 1,131,3,125,6,121,30,124,0,160,18,124,2,124,4,124, - 6,161,3,1,0,116,10,160,11,100,7,124,4,161,2,1, - 0,87,0,110,22,4,0,116,2,107,10,144,1,114,86,1, - 0,1,0,1,0,89,0,110,2,88,0,124,9,83,0,41, - 8,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,130,0,0,0,41,3,114,136,0,0,0,114,102, - 0,0,0,114,37,0,0,0,122,13,123,125,32,109,97,116, - 99,104,101,115,32,123,125,41,3,114,102,0,0,0,114,93, - 0,0,0,114,94,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,155,0,0,0, - 114,83,0,0,0,114,70,0,0,0,114,193,0,0,0,114, - 42,0,0,0,114,16,0,0,0,114,196,0,0,0,114,139, - 0,0,0,114,103,0,0,0,114,134,0,0,0,114,118,0, - 0,0,114,133,0,0,0,114,145,0,0,0,114,202,0,0, - 0,114,8,0,0,0,218,19,100,111,110,116,95,119,114,105, - 116,101,95,98,121,116,101,99,111,100,101,114,148,0,0,0, - 114,33,0,0,0,114,195,0,0,0,41,10,114,104,0,0, - 0,114,123,0,0,0,114,94,0,0,0,114,137,0,0,0, - 114,93,0,0,0,218,2,115,116,114,56,0,0,0,218,10, - 98,121,116,101,115,95,100,97,116,97,114,151,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,6,0,0,0,114,184,0,0,0, - 233,2,0,0,115,78,0,0,0,0,7,10,1,4,1,2, - 1,12,1,14,1,10,2,2,1,14,1,14,1,6,2,12, - 1,2,1,14,1,14,1,6,2,2,1,4,1,4,1,12, - 1,18,1,6,2,8,1,6,1,6,1,2,1,8,1,10, - 1,12,1,12,1,18,1,10,1,6,1,10,1,2,1,14, - 1,16,1,16,1,6,1,122,21,83,111,117,114,99,101,76, - 111,97,100,101,114,46,103,101,116,95,99,111,100,101,78,114, - 91,0,0,0,41,10,114,109,0,0,0,114,108,0,0,0, - 114,110,0,0,0,114,192,0,0,0,114,193,0,0,0,114, - 195,0,0,0,114,194,0,0,0,114,198,0,0,0,114,202, - 0,0,0,114,184,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,191,0,0, - 0,175,2,0,0,115,14,0,0,0,8,2,8,8,8,13, - 8,10,8,7,8,10,14,8,114,191,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,80,0,0,0,101,0,90,1,100,0,90,2,100, + 105,110,100,95,115,112,101,99,99,3,0,0,0,0,0,0, + 0,4,0,0,0,4,0,0,0,67,0,0,0,115,34,0, + 0,0,124,0,160,0,124,1,124,2,161,2,125,3,124,3, + 100,1,107,9,114,26,124,3,106,1,83,0,100,1,83,0, + 100,1,83,0,41,2,122,108,70,105,110,100,32,109,111,100, + 117,108,101,32,110,97,109,101,100,32,105,110,32,116,104,101, + 32,114,101,103,105,115,116,114,121,46,10,10,32,32,32,32, + 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, + 85,115,101,32,101,120,101,99,95,109,111,100,117,108,101,40, + 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, + 32,32,32,32,78,41,2,114,184,0,0,0,114,124,0,0, + 0,41,4,114,174,0,0,0,114,123,0,0,0,114,37,0, + 0,0,114,168,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,218,11,102,105,110,100,95,109,111,100, + 117,108,101,175,2,0,0,115,8,0,0,0,0,7,12,1, + 8,1,6,2,122,33,87,105,110,100,111,119,115,82,101,103, + 105,115,116,114,121,70,105,110,100,101,114,46,102,105,110,100, + 95,109,111,100,117,108,101,41,2,78,78,41,1,78,41,12, + 114,109,0,0,0,114,108,0,0,0,114,110,0,0,0,114, + 111,0,0,0,114,178,0,0,0,114,177,0,0,0,114,176, + 0,0,0,218,11,99,108,97,115,115,109,101,116,104,111,100, + 114,175,0,0,0,114,181,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,6,0,0,0,114,172,0,0,0,125,2,0, + 0,115,18,0,0,0,12,5,4,3,4,2,4,2,12,7, + 12,15,2,1,12,15,2,1,114,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,48,0,0,0,101,0,90,1,100,0,90,2,100, 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, - 0,90,5,100,6,100,7,132,0,90,6,101,7,135,0,102, - 1,100,8,100,9,132,8,131,1,90,8,101,7,100,10,100, - 11,132,0,131,1,90,9,100,12,100,13,132,0,90,10,135, - 0,4,0,90,11,83,0,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,16,0,0,0,124,1,124,0,95,0,124,2, - 124,0,95,1,100,1,83,0,41,2,122,75,67,97,99,104, - 101,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109, - 101,32,97,110,100,32,116,104,101,32,112,97,116,104,32,116, - 111,32,116,104,101,32,102,105,108,101,32,102,111,117,110,100, - 32,98,121,32,116,104,101,10,32,32,32,32,32,32,32,32, - 102,105,110,100,101,114,46,78,41,2,114,102,0,0,0,114, - 37,0,0,0,41,3,114,104,0,0,0,114,123,0,0,0, - 114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,182,0,0,0,34,3,0,0,115,4,0, - 0,0,0,3,6,1,122,19,70,105,108,101,76,111,97,100, - 101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 115,24,0,0,0,124,0,106,0,124,1,106,0,107,2,111, - 22,124,0,106,1,124,1,106,1,107,2,83,0,41,1,78, - 41,2,218,9,95,95,99,108,97,115,115,95,95,114,115,0, - 0,0,41,2,114,104,0,0,0,218,5,111,116,104,101,114, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218, - 6,95,95,101,113,95,95,40,3,0,0,115,4,0,0,0, - 0,1,12,1,122,17,70,105,108,101,76,111,97,100,101,114, - 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0, - 0,116,0,124,0,106,1,131,1,116,0,124,0,106,2,131, - 1,65,0,83,0,41,1,78,41,3,218,4,104,97,115,104, - 114,102,0,0,0,114,37,0,0,0,41,1,114,104,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 218,8,95,95,104,97,115,104,95,95,44,3,0,0,115,2, - 0,0,0,0,1,122,19,70,105,108,101,76,111,97,100,101, + 0,90,5,100,6,100,7,132,0,90,6,100,8,100,9,132, + 0,90,7,100,10,83,0,41,11,218,13,95,76,111,97,100, + 101,114,66,97,115,105,99,115,122,83,66,97,115,101,32,99, + 108,97,115,115,32,111,102,32,99,111,109,109,111,110,32,99, + 111,100,101,32,110,101,101,100,101,100,32,98,121,32,98,111, + 116,104,32,83,111,117,114,99,101,76,111,97,100,101,114,32, + 97,110,100,10,32,32,32,32,83,111,117,114,99,101,108,101, + 115,115,70,105,108,101,76,111,97,100,101,114,46,99,2,0, + 0,0,0,0,0,0,5,0,0,0,4,0,0,0,67,0, + 0,0,115,64,0,0,0,116,0,124,0,160,1,124,1,161, + 1,131,1,100,1,25,0,125,2,124,2,160,2,100,2,100, + 1,161,2,100,3,25,0,125,3,124,1,160,3,100,2,161, + 1,100,4,25,0,125,4,124,3,100,5,107,2,111,62,124, + 4,100,5,107,3,83,0,41,6,122,141,67,111,110,99,114, + 101,116,101,32,105,109,112,108,101,109,101,110,116,97,116,105, + 111,110,32,111,102,32,73,110,115,112,101,99,116,76,111,97, + 100,101,114,46,105,115,95,112,97,99,107,97,103,101,32,98, + 121,32,99,104,101,99,107,105,110,103,32,105,102,10,32,32, + 32,32,32,32,32,32,116,104,101,32,112,97,116,104,32,114, + 101,116,117,114,110,101,100,32,98,121,32,103,101,116,95,102, + 105,108,101,110,97,109,101,32,104,97,115,32,97,32,102,105, + 108,101,110,97,109,101,32,111,102,32,39,95,95,105,110,105, + 116,95,95,46,112,121,39,46,114,31,0,0,0,114,61,0, + 0,0,114,62,0,0,0,114,59,0,0,0,218,8,95,95, + 105,110,105,116,95,95,41,4,114,40,0,0,0,114,161,0, + 0,0,114,36,0,0,0,114,34,0,0,0,41,5,114,104, + 0,0,0,114,123,0,0,0,114,98,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,6,0,0,0,114,163,0,0,0,194,2,0,0,115, + 8,0,0,0,0,3,18,1,16,1,14,1,122,24,95,76, + 111,97,100,101,114,66,97,115,105,99,115,46,105,115,95,112, + 97,99,107,97,103,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, + 100,1,83,0,41,2,122,42,85,115,101,32,100,101,102,97, + 117,108,116,32,115,101,109,97,110,116,105,99,115,32,102,111, + 114,32,109,111,100,117,108,101,32,99,114,101,97,116,105,111, + 110,46,78,114,4,0,0,0,41,2,114,104,0,0,0,114, + 168,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,218,13,99,114,101,97,116,101,95,109,111,100,117, + 108,101,202,2,0,0,115,0,0,0,0,122,27,95,76,111, + 97,100,101,114,66,97,115,105,99,115,46,99,114,101,97,116, + 101,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, + 0,3,0,0,0,5,0,0,0,67,0,0,0,115,56,0, + 0,0,124,0,160,0,124,1,106,1,161,1,125,2,124,2, + 100,1,107,8,114,36,116,2,100,2,160,3,124,1,106,1, + 161,1,131,1,130,1,116,4,160,5,116,6,124,2,124,1, + 106,7,161,3,1,0,100,1,83,0,41,3,122,19,69,120, + 101,99,117,116,101,32,116,104,101,32,109,111,100,117,108,101, + 46,78,122,52,99,97,110,110,111,116,32,108,111,97,100,32, + 109,111,100,117,108,101,32,123,33,114,125,32,119,104,101,110, + 32,103,101,116,95,99,111,100,101,40,41,32,114,101,116,117, + 114,110,115,32,78,111,110,101,41,8,218,8,103,101,116,95, + 99,111,100,101,114,109,0,0,0,114,103,0,0,0,114,50, + 0,0,0,114,118,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,115,0,0,0,41,3, + 114,104,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,6,0,0, + 0,218,11,101,120,101,99,95,109,111,100,117,108,101,205,2, + 0,0,115,10,0,0,0,0,2,12,1,8,1,6,1,10, + 1,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, + 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,4,0,0,0,67,0,0, + 0,115,12,0,0,0,116,0,160,1,124,0,124,1,161,2, + 83,0,41,1,122,26,84,104,105,115,32,109,111,100,117,108, + 101,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, + 41,2,114,118,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,104,0,0, + 0,114,123,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,218,11,108,111,97,100,95,109,111,100,117, + 108,101,213,2,0,0,115,2,0,0,0,0,2,122,25,95, + 76,111,97,100,101,114,66,97,115,105,99,115,46,108,111,97, + 100,95,109,111,100,117,108,101,78,41,8,114,109,0,0,0, + 114,108,0,0,0,114,110,0,0,0,114,111,0,0,0,114, + 163,0,0,0,114,189,0,0,0,114,194,0,0,0,114,196, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,114,187,0,0,0,189,2,0,0, + 115,8,0,0,0,12,5,8,8,8,3,8,8,114,187,0, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,64,0,0,0,115,74,0,0,0,101,0,90,1, + 100,0,90,2,100,1,100,2,132,0,90,3,100,3,100,4, + 132,0,90,4,100,5,100,6,132,0,90,5,100,7,100,8, + 132,0,90,6,100,9,100,10,132,0,90,7,100,18,100,12, + 156,1,100,13,100,14,132,2,90,8,100,15,100,16,132,0, + 90,9,100,17,83,0,41,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,8,0,0,0, + 116,0,130,1,100,1,83,0,41,2,122,178,79,112,116,105, + 111,110,97,108,32,109,101,116,104,111,100,32,116,104,97,116, + 32,114,101,116,117,114,110,115,32,116,104,101,32,109,111,100, + 105,102,105,99,97,116,105,111,110,32,116,105,109,101,32,40, + 97,110,32,105,110,116,41,32,102,111,114,32,116,104,101,10, + 32,32,32,32,32,32,32,32,115,112,101,99,105,102,105,101, + 100,32,112,97,116,104,44,32,119,104,101,114,101,32,112,97, + 116,104,32,105,115,32,97,32,115,116,114,46,10,10,32,32, + 32,32,32,32,32,32,82,97,105,115,101,115,32,79,83,69, + 114,114,111,114,32,119,104,101,110,32,116,104,101,32,112,97, + 116,104,32,99,97,110,110,111,116,32,98,101,32,104,97,110, + 100,108,101,100,46,10,32,32,32,32,32,32,32,32,78,41, + 1,114,42,0,0,0,41,2,114,104,0,0,0,114,37,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,218,10,112,97,116,104,95,109,116,105,109,101,220,2,0, + 0,115,2,0,0,0,0,6,122,23,83,111,117,114,99,101, + 76,111,97,100,101,114,46,112,97,116,104,95,109,116,105,109, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,67,0,0,0,115,14,0,0,0,100,1,124,0,160, + 0,124,1,161,1,105,1,83,0,41,2,97,170,1,0,0, + 79,112,116,105,111,110,97,108,32,109,101,116,104,111,100,32, + 114,101,116,117,114,110,105,110,103,32,97,32,109,101,116,97, + 100,97,116,97,32,100,105,99,116,32,102,111,114,32,116,104, + 101,32,115,112,101,99,105,102,105,101,100,32,112,97,116,104, + 10,32,32,32,32,32,32,32,32,116,111,32,98,121,32,116, + 104,101,32,112,97,116,104,32,40,115,116,114,41,46,10,32, + 32,32,32,32,32,32,32,80,111,115,115,105,98,108,101,32, + 107,101,121,115,58,10,32,32,32,32,32,32,32,32,45,32, + 39,109,116,105,109,101,39,32,40,109,97,110,100,97,116,111, + 114,121,41,32,105,115,32,116,104,101,32,110,117,109,101,114, + 105,99,32,116,105,109,101,115,116,97,109,112,32,111,102,32, + 108,97,115,116,32,115,111,117,114,99,101,10,32,32,32,32, + 32,32,32,32,32,32,99,111,100,101,32,109,111,100,105,102, + 105,99,97,116,105,111,110,59,10,32,32,32,32,32,32,32, + 32,45,32,39,115,105,122,101,39,32,40,111,112,116,105,111, + 110,97,108,41,32,105,115,32,116,104,101,32,115,105,122,101, + 32,105,110,32,98,121,116,101,115,32,111,102,32,116,104,101, + 32,115,111,117,114,99,101,32,99,111,100,101,46,10,10,32, + 32,32,32,32,32,32,32,73,109,112,108,101,109,101,110,116, + 105,110,103,32,116,104,105,115,32,109,101,116,104,111,100,32, + 97,108,108,111,119,115,32,116,104,101,32,108,111,97,100,101, + 114,32,116,111,32,114,101,97,100,32,98,121,116,101,99,111, + 100,101,32,102,105,108,101,115,46,10,32,32,32,32,32,32, + 32,32,82,97,105,115,101,115,32,79,83,69,114,114,111,114, + 32,119,104,101,110,32,116,104,101,32,112,97,116,104,32,99, + 97,110,110,111,116,32,98,101,32,104,97,110,100,108,101,100, + 46,10,32,32,32,32,32,32,32,32,114,151,0,0,0,41, + 1,114,198,0,0,0,41,2,114,104,0,0,0,114,37,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,218,10,112,97,116,104,95,115,116,97,116,115,228,2,0, + 0,115,2,0,0,0,0,11,122,23,83,111,117,114,99,101, + 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, + 115,99,4,0,0,0,0,0,0,0,4,0,0,0,4,0, + 0,0,67,0,0,0,115,12,0,0,0,124,0,160,0,124, + 2,124,3,161,2,83,0,41,1,122,228,79,112,116,105,111, + 110,97,108,32,109,101,116,104,111,100,32,119,104,105,99,104, + 32,119,114,105,116,101,115,32,100,97,116,97,32,40,98,121, + 116,101,115,41,32,116,111,32,97,32,102,105,108,101,32,112, + 97,116,104,32,40,97,32,115,116,114,41,46,10,10,32,32, + 32,32,32,32,32,32,73,109,112,108,101,109,101,110,116,105, + 110,103,32,116,104,105,115,32,109,101,116,104,111,100,32,97, + 108,108,111,119,115,32,102,111,114,32,116,104,101,32,119,114, + 105,116,105,110,103,32,111,102,32,98,121,116,101,99,111,100, + 101,32,102,105,108,101,115,46,10,10,32,32,32,32,32,32, + 32,32,84,104,101,32,115,111,117,114,99,101,32,112,97,116, + 104,32,105,115,32,110,101,101,100,101,100,32,105,110,32,111, + 114,100,101,114,32,116,111,32,99,111,114,114,101,99,116,108, + 121,32,116,114,97,110,115,102,101,114,32,112,101,114,109,105, + 115,115,105,111,110,115,10,32,32,32,32,32,32,32,32,41, + 1,218,8,115,101,116,95,100,97,116,97,41,4,114,104,0, + 0,0,114,94,0,0,0,90,10,99,97,99,104,101,95,112, + 97,116,104,114,56,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,218,15,95,99,97,99,104,101,95, + 98,121,116,101,99,111,100,101,241,2,0,0,115,2,0,0, + 0,0,8,122,28,83,111,117,114,99,101,76,111,97,100,101, + 114,46,95,99,97,99,104,101,95,98,121,116,101,99,111,100, + 101,99,3,0,0,0,0,0,0,0,3,0,0,0,1,0, + 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, + 2,122,150,79,112,116,105,111,110,97,108,32,109,101,116,104, + 111,100,32,119,104,105,99,104,32,119,114,105,116,101,115,32, + 100,97,116,97,32,40,98,121,116,101,115,41,32,116,111,32, + 97,32,102,105,108,101,32,112,97,116,104,32,40,97,32,115, + 116,114,41,46,10,10,32,32,32,32,32,32,32,32,73,109, + 112,108,101,109,101,110,116,105,110,103,32,116,104,105,115,32, + 109,101,116,104,111,100,32,97,108,108,111,119,115,32,102,111, + 114,32,116,104,101,32,119,114,105,116,105,110,103,32,111,102, + 32,98,121,116,101,99,111,100,101,32,102,105,108,101,115,46, + 10,32,32,32,32,32,32,32,32,78,114,4,0,0,0,41, + 3,114,104,0,0,0,114,37,0,0,0,114,56,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, + 200,0,0,0,251,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,82,0,0,0,124,0, + 160,0,124,1,161,1,125,2,121,14,124,0,160,1,124,2, + 161,1,125,3,87,0,110,48,4,0,116,2,107,10,114,72, + 1,0,125,4,1,0,122,20,116,3,100,1,124,1,100,2, + 141,2,124,4,130,2,87,0,89,0,100,3,100,3,125,4, + 126,4,88,0,110,2,88,0,116,4,124,3,131,1,83,0, + 41,4,122,52,67,111,110,99,114,101,116,101,32,105,109,112, + 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,73, + 110,115,112,101,99,116,76,111,97,100,101,114,46,103,101,116, + 95,115,111,117,114,99,101,46,122,39,115,111,117,114,99,101, + 32,110,111,116,32,97,118,97,105,108,97,98,108,101,32,116, + 104,114,111,117,103,104,32,103,101,116,95,100,97,116,97,40, + 41,41,1,114,102,0,0,0,78,41,5,114,161,0,0,0, + 218,8,103,101,116,95,100,97,116,97,114,42,0,0,0,114, + 103,0,0,0,114,159,0,0,0,41,5,114,104,0,0,0, + 114,123,0,0,0,114,37,0,0,0,114,157,0,0,0,218, + 3,101,120,99,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,218,10,103,101,116,95,115,111,117,114,99,101,2, + 3,0,0,115,14,0,0,0,0,2,10,1,2,1,14,1, + 16,1,4,1,28,1,122,23,83,111,117,114,99,101,76,111, + 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,114, + 31,0,0,0,41,1,218,9,95,111,112,116,105,109,105,122, + 101,99,3,0,0,0,1,0,0,0,4,0,0,0,8,0, + 0,0,67,0,0,0,115,22,0,0,0,116,0,106,1,116, + 2,124,1,124,2,100,1,100,2,124,3,100,3,141,6,83, + 0,41,4,122,130,82,101,116,117,114,110,32,116,104,101,32, + 99,111,100,101,32,111,98,106,101,99,116,32,99,111,109,112, + 105,108,101,100,32,102,114,111,109,32,115,111,117,114,99,101, + 46,10,10,32,32,32,32,32,32,32,32,84,104,101,32,39, + 100,97,116,97,39,32,97,114,103,117,109,101,110,116,32,99, + 97,110,32,98,101,32,97,110,121,32,111,98,106,101,99,116, + 32,116,121,112,101,32,116,104,97,116,32,99,111,109,112,105, + 108,101,40,41,32,115,117,112,112,111,114,116,115,46,10,32, + 32,32,32,32,32,32,32,114,192,0,0,0,84,41,2,218, + 12,100,111,110,116,95,105,110,104,101,114,105,116,114,72,0, + 0,0,41,3,114,118,0,0,0,114,191,0,0,0,218,7, + 99,111,109,112,105,108,101,41,4,114,104,0,0,0,114,56, + 0,0,0,114,37,0,0,0,114,205,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,6,0,0,0,218,14,115,111, + 117,114,99,101,95,116,111,95,99,111,100,101,12,3,0,0, + 115,4,0,0,0,0,5,12,1,122,27,83,111,117,114,99, + 101,76,111,97,100,101,114,46,115,111,117,114,99,101,95,116, + 111,95,99,111,100,101,99,2,0,0,0,0,0,0,0,15, + 0,0,0,43,0,0,0,67,0,0,0,115,46,2,0,0, + 124,0,160,0,124,1,161,1,125,2,100,1,125,3,100,1, + 125,4,100,1,125,5,100,2,125,6,100,3,125,7,121,12, + 116,1,124,2,131,1,125,8,87,0,110,26,4,0,116,2, + 107,10,114,68,1,0,1,0,1,0,100,1,125,8,89,0, + 144,1,110,48,88,0,121,14,124,0,160,3,124,2,161,1, + 125,9,87,0,110,22,4,0,116,4,107,10,114,106,1,0, + 1,0,1,0,89,0,144,1,110,10,88,0,116,5,124,9, + 100,4,25,0,131,1,125,3,121,14,124,0,160,6,124,8, + 161,1,125,10,87,0,110,20,4,0,116,4,107,10,114,154, + 1,0,1,0,1,0,89,0,110,218,88,0,124,1,124,8, + 100,5,156,2,125,11,121,148,116,7,124,10,124,1,124,11, + 131,3,125,12,116,8,124,10,131,1,100,6,100,1,133,2, + 25,0,125,13,124,12,100,7,64,0,100,8,107,3,125,6, + 124,6,144,1,114,36,124,12,100,9,64,0,100,8,107,3, + 125,7,116,9,106,10,100,10,107,3,144,1,114,56,124,7, + 115,254,116,9,106,10,100,11,107,2,144,1,114,56,124,0, + 160,6,124,2,161,1,125,4,116,9,160,11,116,12,124,4, + 161,2,125,5,116,13,124,10,124,5,124,1,124,11,131,4, + 1,0,110,20,116,14,124,10,124,3,124,9,100,12,25,0, + 124,1,124,11,131,5,1,0,87,0,110,26,4,0,116,15, + 116,16,102,2,107,10,144,1,114,84,1,0,1,0,1,0, + 89,0,110,32,88,0,116,17,160,18,100,13,124,8,124,2, + 161,3,1,0,116,19,124,13,124,1,124,8,124,2,100,14, + 141,4,83,0,124,4,100,1,107,8,144,1,114,136,124,0, + 160,6,124,2,161,1,125,4,124,0,160,20,124,4,124,2, + 161,2,125,14,116,17,160,18,100,15,124,2,161,2,1,0, + 116,21,106,22,144,2,115,42,124,8,100,1,107,9,144,2, + 114,42,124,3,100,1,107,9,144,2,114,42,124,6,144,1, + 114,228,124,5,100,1,107,8,144,1,114,214,116,9,160,11, + 124,4,161,1,125,5,116,23,124,14,124,5,124,7,131,3, + 125,10,110,16,116,24,124,14,124,3,116,25,124,4,131,1, + 131,3,125,10,121,30,124,0,160,26,124,2,124,8,124,10, + 161,3,1,0,116,17,160,18,100,16,124,8,161,2,1,0, + 87,0,110,22,4,0,116,2,107,10,144,2,114,40,1,0, + 1,0,1,0,89,0,110,2,88,0,124,14,83,0,41,17, + 122,190,67,111,110,99,114,101,116,101,32,105,109,112,108,101, + 109,101,110,116,97,116,105,111,110,32,111,102,32,73,110,115, + 112,101,99,116,76,111,97,100,101,114,46,103,101,116,95,99, + 111,100,101,46,10,10,32,32,32,32,32,32,32,32,82,101, + 97,100,105,110,103,32,111,102,32,98,121,116,101,99,111,100, + 101,32,114,101,113,117,105,114,101,115,32,112,97,116,104,95, + 115,116,97,116,115,32,116,111,32,98,101,32,105,109,112,108, + 101,109,101,110,116,101,100,46,32,84,111,32,119,114,105,116, + 101,10,32,32,32,32,32,32,32,32,98,121,116,101,99,111, + 100,101,44,32,115,101,116,95,100,97,116,97,32,109,117,115, + 116,32,97,108,115,111,32,98,101,32,105,109,112,108,101,109, + 101,110,116,101,100,46,10,10,32,32,32,32,32,32,32,32, + 78,70,84,114,151,0,0,0,41,2,114,102,0,0,0,114, + 37,0,0,0,114,128,0,0,0,114,31,0,0,0,114,62, + 0,0,0,114,59,0,0,0,90,5,110,101,118,101,114,90, + 6,97,108,119,97,121,115,218,4,115,105,122,101,122,13,123, + 125,32,109,97,116,99,104,101,115,32,123,125,41,3,114,102, + 0,0,0,114,93,0,0,0,114,94,0,0,0,122,19,99, + 111,100,101,32,111,98,106,101,99,116,32,102,114,111,109,32, + 123,125,122,10,119,114,111,116,101,32,123,33,114,125,41,27, + 114,161,0,0,0,114,83,0,0,0,114,70,0,0,0,114, + 199,0,0,0,114,42,0,0,0,114,16,0,0,0,114,202, + 0,0,0,114,135,0,0,0,218,10,109,101,109,111,114,121, + 118,105,101,119,114,145,0,0,0,90,21,99,104,101,99,107, + 95,104,97,115,104,95,98,97,115,101,100,95,112,121,99,115, + 114,140,0,0,0,218,17,95,82,65,87,95,77,65,71,73, + 67,95,78,85,77,66,69,82,114,141,0,0,0,114,139,0, + 0,0,114,103,0,0,0,114,133,0,0,0,114,118,0,0, + 0,114,132,0,0,0,114,147,0,0,0,114,208,0,0,0, + 114,8,0,0,0,218,19,100,111,110,116,95,119,114,105,116, + 101,95,98,121,116,101,99,111,100,101,114,154,0,0,0,114, + 152,0,0,0,114,33,0,0,0,114,201,0,0,0,41,15, + 114,104,0,0,0,114,123,0,0,0,114,94,0,0,0,114, + 137,0,0,0,114,157,0,0,0,114,140,0,0,0,90,10, + 104,97,115,104,95,98,97,115,101,100,90,12,99,104,101,99, + 107,95,115,111,117,114,99,101,114,93,0,0,0,218,2,115, + 116,114,56,0,0,0,114,134,0,0,0,114,71,0,0,0, + 90,10,98,121,116,101,115,95,100,97,116,97,90,11,99,111, + 100,101,95,111,98,106,101,99,116,114,4,0,0,0,114,4, + 0,0,0,114,6,0,0,0,114,190,0,0,0,20,3,0, + 0,115,134,0,0,0,0,7,10,1,4,1,4,1,4,1, + 4,1,4,1,2,1,12,1,14,1,12,2,2,1,14,1, + 14,1,8,2,12,1,2,1,14,1,14,1,6,3,2,1, + 8,2,2,1,12,1,16,1,12,1,6,1,12,1,12,1, + 4,1,12,1,10,1,4,1,2,1,6,2,8,1,8,2, + 2,1,2,1,2,1,6,1,2,1,10,2,20,1,6,2, + 8,1,6,1,6,1,2,1,8,1,10,1,10,1,12,1, + 12,1,18,1,10,1,6,1,10,1,10,1,14,2,6,1, + 10,1,2,1,14,1,16,1,16,1,6,1,122,21,83,111, + 117,114,99,101,76,111,97,100,101,114,46,103,101,116,95,99, + 111,100,101,78,114,91,0,0,0,41,10,114,109,0,0,0, + 114,108,0,0,0,114,110,0,0,0,114,198,0,0,0,114, + 199,0,0,0,114,201,0,0,0,114,200,0,0,0,114,204, + 0,0,0,114,208,0,0,0,114,190,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,114,197,0,0,0,218,2,0,0,115,14,0,0,0,8, + 2,8,8,8,13,8,10,8,7,8,10,14,8,114,197,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,80,0,0,0,101,0,90,1, + 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, + 100,4,100,5,132,0,90,5,100,6,100,7,132,0,90,6, + 101,7,135,0,102,1,100,8,100,9,132,8,131,1,90,8, + 101,7,100,10,100,11,132,0,131,1,90,9,100,12,100,13, + 132,0,90,10,135,0,4,0,90,11,83,0,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,16,0,0,0,124,1,124, + 0,95,0,124,2,124,0,95,1,100,1,83,0,41,2,122, + 75,67,97,99,104,101,32,116,104,101,32,109,111,100,117,108, + 101,32,110,97,109,101,32,97,110,100,32,116,104,101,32,112, + 97,116,104,32,116,111,32,116,104,101,32,102,105,108,101,32, + 102,111,117,110,100,32,98,121,32,116,104,101,10,32,32,32, + 32,32,32,32,32,102,105,110,100,101,114,46,78,41,2,114, + 102,0,0,0,114,37,0,0,0,41,3,114,104,0,0,0, + 114,123,0,0,0,114,37,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,114,188,0,0,0,111,3, + 0,0,115,4,0,0,0,0,3,6,1,122,19,70,105,108, + 101,76,111,97,100,101,114,46,95,95,105,110,105,116,95,95, + 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, + 0,67,0,0,0,115,24,0,0,0,124,0,106,0,124,1, + 106,0,107,2,111,22,124,0,106,1,124,1,106,1,107,2, + 83,0,41,1,78,41,2,218,9,95,95,99,108,97,115,115, + 95,95,114,115,0,0,0,41,2,114,104,0,0,0,218,5, + 111,116,104,101,114,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,218,6,95,95,101,113,95,95,117,3,0,0, + 115,4,0,0,0,0,1,12,1,122,17,70,105,108,101,76, + 111,97,100,101,114,46,95,95,101,113,95,95,99,1,0,0, + 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, + 0,115,20,0,0,0,116,0,124,0,106,1,131,1,116,0, + 124,0,106,2,131,1,65,0,83,0,41,1,78,41,3,218, + 4,104,97,115,104,114,102,0,0,0,114,37,0,0,0,41, + 1,114,104,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,218,8,95,95,104,97,115,104,95,95,121, + 3,0,0,115,2,0,0,0,0,1,122,19,70,105,108,101, + 76,111,97,100,101,114,46,95,95,104,97,115,104,95,95,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 3,0,0,0,115,16,0,0,0,116,0,116,1,124,0,131, + 2,160,2,124,1,161,1,83,0,41,1,122,100,76,111,97, + 100,32,97,32,109,111,100,117,108,101,32,102,114,111,109,32, + 97,32,102,105,108,101,46,10,10,32,32,32,32,32,32,32, + 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, + 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, + 32,101,120,101,99,95,109,111,100,117,108,101,40,41,32,105, + 110,115,116,101,97,100,46,10,10,32,32,32,32,32,32,32, + 32,41,3,218,5,115,117,112,101,114,114,214,0,0,0,114, + 196,0,0,0,41,2,114,104,0,0,0,114,123,0,0,0, + 41,1,114,215,0,0,0,114,4,0,0,0,114,6,0,0, + 0,114,196,0,0,0,124,3,0,0,115,2,0,0,0,0, + 10,122,22,70,105,108,101,76,111,97,100,101,114,46,108,111, + 97,100,95,109,111,100,117,108,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,6, + 0,0,0,124,0,106,0,83,0,41,1,122,58,82,101,116, + 117,114,110,32,116,104,101,32,112,97,116,104,32,116,111,32, + 116,104,101,32,115,111,117,114,99,101,32,102,105,108,101,32, + 97,115,32,102,111,117,110,100,32,98,121,32,116,104,101,32, + 102,105,110,100,101,114,46,41,1,114,37,0,0,0,41,2, + 114,104,0,0,0,114,123,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,114,161,0,0,0,136,3, + 0,0,115,2,0,0,0,0,3,122,23,70,105,108,101,76, + 111,97,100,101,114,46,103,101,116,95,102,105,108,101,110,97, + 109,101,99,2,0,0,0,0,0,0,0,3,0,0,0,9, + 0,0,0,67,0,0,0,115,32,0,0,0,116,0,160,1, + 124,1,100,1,161,2,143,10,125,2,124,2,160,2,161,0, + 83,0,81,0,82,0,88,0,100,2,83,0,41,3,122,39, + 82,101,116,117,114,110,32,116,104,101,32,100,97,116,97,32, + 102,114,111,109,32,112,97,116,104,32,97,115,32,114,97,119, + 32,98,121,116,101,115,46,218,1,114,78,41,3,114,52,0, + 0,0,114,53,0,0,0,90,4,114,101,97,100,41,3,114, + 104,0,0,0,114,37,0,0,0,114,57,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,6,0,0,0,114,202,0, + 0,0,141,3,0,0,115,4,0,0,0,0,2,14,1,122, + 19,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, + 100,97,116,97,41,12,114,109,0,0,0,114,108,0,0,0, + 114,110,0,0,0,114,111,0,0,0,114,188,0,0,0,114, + 217,0,0,0,114,219,0,0,0,114,120,0,0,0,114,196, + 0,0,0,114,161,0,0,0,114,202,0,0,0,90,13,95, + 95,99,108,97,115,115,99,101,108,108,95,95,114,4,0,0, + 0,114,4,0,0,0,41,1,114,215,0,0,0,114,6,0, + 0,0,114,214,0,0,0,106,3,0,0,115,12,0,0,0, + 12,5,8,6,8,4,8,3,16,12,12,5,114,214,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,64,0,0,0,115,46,0,0,0,101,0,90,1,100, + 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, + 4,100,5,132,0,90,5,100,6,100,7,156,1,100,8,100, + 9,132,2,90,6,100,10,83,0,41,11,218,16,83,111,117, + 114,99,101,70,105,108,101,76,111,97,100,101,114,122,62,67, + 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,111,102,32,83,111,117,114,99,101, + 76,111,97,100,101,114,32,117,115,105,110,103,32,116,104,101, + 32,102,105,108,101,32,115,121,115,116,101,109,46,99,2,0, + 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, + 0,0,115,22,0,0,0,116,0,124,1,131,1,125,2,124, + 2,106,1,124,2,106,2,100,1,156,2,83,0,41,2,122, + 33,82,101,116,117,114,110,32,116,104,101,32,109,101,116,97, + 100,97,116,97,32,102,111,114,32,116,104,101,32,112,97,116, + 104,46,41,2,114,151,0,0,0,114,209,0,0,0,41,3, + 114,41,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,104,0,0,0,114, + 37,0,0,0,114,213,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,6,0,0,0,114,199,0,0,0,151,3,0, + 0,115,4,0,0,0,0,2,8,1,122,27,83,111,117,114, + 99,101,70,105,108,101,76,111,97,100,101,114,46,112,97,116, + 104,95,115,116,97,116,115,99,4,0,0,0,0,0,0,0, + 5,0,0,0,5,0,0,0,67,0,0,0,115,24,0,0, + 0,116,0,124,1,131,1,125,4,124,0,106,1,124,2,124, + 3,124,4,100,1,141,3,83,0,41,2,78,41,1,218,5, + 95,109,111,100,101,41,2,114,101,0,0,0,114,200,0,0, + 0,41,5,114,104,0,0,0,114,94,0,0,0,114,93,0, + 0,0,114,56,0,0,0,114,44,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,6,0,0,0,114,201,0,0,0, + 156,3,0,0,115,4,0,0,0,0,2,8,1,122,32,83, + 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,46, + 95,99,97,99,104,101,95,98,121,116,101,99,111,100,101,105, + 182,1,0,0,41,1,114,224,0,0,0,99,3,0,0,0, + 1,0,0,0,9,0,0,0,18,0,0,0,67,0,0,0, + 115,248,0,0,0,116,0,124,1,131,1,92,2,125,4,125, + 5,103,0,125,6,120,38,124,4,114,54,116,1,124,4,131, + 1,115,54,116,0,124,4,131,1,92,2,125,4,125,7,124, + 6,160,2,124,7,161,1,1,0,113,18,87,0,120,108,116, + 3,124,6,131,1,68,0,93,96,125,7,116,4,124,4,124, + 7,131,2,125,4,121,14,116,5,160,6,124,4,161,1,1, + 0,87,0,113,66,4,0,116,7,107,10,114,116,1,0,1, + 0,1,0,119,66,89,0,113,66,4,0,116,8,107,10,114, + 160,1,0,125,8,1,0,122,18,116,9,160,10,100,1,124, + 4,124,8,161,3,1,0,100,2,83,0,100,2,125,8,126, + 8,88,0,113,66,88,0,113,66,87,0,121,28,116,11,124, + 1,124,2,124,3,131,3,1,0,116,9,160,10,100,3,124, + 1,161,2,1,0,87,0,110,48,4,0,116,8,107,10,114, + 242,1,0,125,8,1,0,122,20,116,9,160,10,100,1,124, + 1,124,8,161,3,1,0,87,0,89,0,100,2,100,2,125, + 8,126,8,88,0,110,2,88,0,100,2,83,0,41,4,122, + 27,87,114,105,116,101,32,98,121,116,101,115,32,100,97,116, + 97,32,116,111,32,97,32,102,105,108,101,46,122,27,99,111, + 117,108,100,32,110,111,116,32,99,114,101,97,116,101,32,123, + 33,114,125,58,32,123,33,114,125,78,122,12,99,114,101,97, + 116,101,100,32,123,33,114,125,41,12,114,40,0,0,0,114, + 48,0,0,0,114,167,0,0,0,114,35,0,0,0,114,30, + 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,42,0,0,0,114,118,0,0,0,114,132,0,0,0,114, + 58,0,0,0,41,9,114,104,0,0,0,114,37,0,0,0, + 114,56,0,0,0,114,224,0,0,0,218,6,112,97,114,101, + 110,116,114,98,0,0,0,114,29,0,0,0,114,25,0,0, + 0,114,203,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,114,200,0,0,0,161,3,0,0,115,42, + 0,0,0,0,2,12,1,4,2,14,1,12,1,14,2,14, + 1,10,1,2,1,14,1,14,2,6,1,16,3,6,1,8, + 1,20,1,2,1,12,1,16,1,16,2,8,1,122,25,83, + 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,46, + 115,101,116,95,100,97,116,97,78,41,7,114,109,0,0,0, + 114,108,0,0,0,114,110,0,0,0,114,111,0,0,0,114, + 199,0,0,0,114,201,0,0,0,114,200,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, + 0,0,114,222,0,0,0,147,3,0,0,115,6,0,0,0, + 12,4,8,5,8,5,114,222,0,0,0,99,0,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0, + 115,32,0,0,0,101,0,90,1,100,0,90,2,100,1,90, + 3,100,2,100,3,132,0,90,4,100,4,100,5,132,0,90, + 5,100,6,83,0,41,7,218,20,83,111,117,114,99,101,108, + 101,115,115,70,105,108,101,76,111,97,100,101,114,122,45,76, + 111,97,100,101,114,32,119,104,105,99,104,32,104,97,110,100, + 108,101,115,32,115,111,117,114,99,101,108,101,115,115,32,102, + 105,108,101,32,105,109,112,111,114,116,115,46,99,2,0,0, + 0,0,0,0,0,5,0,0,0,5,0,0,0,67,0,0, + 0,115,68,0,0,0,124,0,160,0,124,1,161,1,125,2, + 124,0,160,1,124,2,161,1,125,3,124,1,124,2,100,1, + 156,2,125,4,116,2,124,3,124,1,124,4,131,3,1,0, + 116,3,116,4,124,3,131,1,100,2,100,0,133,2,25,0, + 124,1,124,2,100,3,141,3,83,0,41,4,78,41,2,114, + 102,0,0,0,114,37,0,0,0,114,128,0,0,0,41,2, + 114,102,0,0,0,114,93,0,0,0,41,5,114,161,0,0, + 0,114,202,0,0,0,114,135,0,0,0,114,147,0,0,0, + 114,210,0,0,0,41,5,114,104,0,0,0,114,123,0,0, + 0,114,37,0,0,0,114,56,0,0,0,114,134,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, + 190,0,0,0,196,3,0,0,115,18,0,0,0,0,1,10, + 1,10,4,2,1,8,2,12,1,2,1,14,1,2,1,122, + 29,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, + 111,97,100,101,114,46,103,101,116,95,99,111,100,101,99,2, + 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, + 0,0,0,115,4,0,0,0,100,1,83,0,41,2,122,39, + 82,101,116,117,114,110,32,78,111,110,101,32,97,115,32,116, + 104,101,114,101,32,105,115,32,110,111,32,115,111,117,114,99, + 101,32,99,111,100,101,46,78,114,4,0,0,0,41,2,114, + 104,0,0,0,114,123,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,6,0,0,0,114,204,0,0,0,212,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,109,0,0, + 0,114,108,0,0,0,114,110,0,0,0,114,111,0,0,0, + 114,190,0,0,0,114,204,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,227, + 0,0,0,192,3,0,0,115,4,0,0,0,12,4,8,16, + 114,227,0,0,0,99,0,0,0,0,0,0,0,0,0,0, + 0,0,3,0,0,0,64,0,0,0,115,92,0,0,0,101, + 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, + 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, + 0,90,6,100,8,100,9,132,0,90,7,100,10,100,11,132, + 0,90,8,100,12,100,13,132,0,90,9,100,14,100,15,132, + 0,90,10,100,16,100,17,132,0,90,11,101,12,100,18,100, + 19,132,0,131,1,90,13,100,20,83,0,41,21,218,19,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,122,93,76,111,97,100,101,114,32,102,111,114,32,101, + 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,115, + 46,10,10,32,32,32,32,84,104,101,32,99,111,110,115,116, + 114,117,99,116,111,114,32,105,115,32,100,101,115,105,103,110, + 101,100,32,116,111,32,119,111,114,107,32,119,105,116,104,32, + 70,105,108,101,70,105,110,100,101,114,46,10,10,32,32,32, + 32,99,3,0,0,0,0,0,0,0,3,0,0,0,2,0, + 0,0,67,0,0,0,115,16,0,0,0,124,1,124,0,95, + 0,124,2,124,0,95,1,100,0,83,0,41,1,78,41,2, + 114,102,0,0,0,114,37,0,0,0,41,3,114,104,0,0, + 0,114,102,0,0,0,114,37,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,6,0,0,0,114,188,0,0,0,229, + 3,0,0,115,4,0,0,0,0,1,6,1,122,28,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,46,95,95,105,110,105,116,95,95,99,2,0,0,0,0, + 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, + 24,0,0,0,124,0,106,0,124,1,106,0,107,2,111,22, + 124,0,106,1,124,1,106,1,107,2,83,0,41,1,78,41, + 2,114,215,0,0,0,114,115,0,0,0,41,2,114,104,0, + 0,0,114,216,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,114,217,0,0,0,233,3,0,0,115, + 4,0,0,0,0,1,12,1,122,26,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,95,95, + 101,113,95,95,99,1,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,115,20,0,0,0,116,0, + 124,0,106,1,131,1,116,0,124,0,106,2,131,1,65,0, + 83,0,41,1,78,41,3,114,218,0,0,0,114,102,0,0, + 0,114,37,0,0,0,41,1,114,104,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,6,0,0,0,114,219,0,0, + 0,237,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,2,0,0,0,3,0,0,0,3,0,0,0,115, - 16,0,0,0,116,0,116,1,124,0,131,2,160,2,124,1, - 161,1,83,0,41,1,122,100,76,111,97,100,32,97,32,109, - 111,100,117,108,101,32,102,114,111,109,32,97,32,102,105,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, - 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, - 100,46,10,10,32,32,32,32,32,32,32,32,41,3,218,5, - 115,117,112,101,114,114,206,0,0,0,114,190,0,0,0,41, - 2,114,104,0,0,0,114,123,0,0,0,41,1,114,207,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,190,0,0, - 0,47,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,0,0,3,0,0,0,5,0,0,0,67,0,0,0,115, + 36,0,0,0,116,0,160,1,116,2,106,3,124,1,161,2, + 125,2,116,0,160,4,100,1,124,1,106,5,124,0,106,6, + 161,3,1,0,124,2,83,0,41,2,122,38,67,114,101,97, + 116,101,32,97,110,32,117,110,105,116,105,97,108,105,122,101, + 100,32,101,120,116,101,110,115,105,111,110,32,109,111,100,117, + 108,101,122,38,101,120,116,101,110,115,105,111,110,32,109,111, + 100,117,108,101,32,123,33,114,125,32,108,111,97,100,101,100, + 32,102,114,111,109,32,123,33,114,125,41,7,114,118,0,0, + 0,114,191,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,132,0,0,0, + 114,102,0,0,0,114,37,0,0,0,41,3,114,104,0,0, + 0,114,168,0,0,0,114,193,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,6,0,0,0,114,189,0,0,0,240, + 3,0,0,115,10,0,0,0,0,2,4,1,10,1,6,1, + 12,1,122,33,69,120,116,101,110,115,105,111,110,70,105,108, + 101,76,111,97,100,101,114,46,99,114,101,97,116,101,95,109, + 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,5,0,0,0,67,0,0,0,115,36,0,0,0,116, + 0,160,1,116,2,106,3,124,1,161,2,1,0,116,0,160, + 4,100,1,124,0,106,5,124,0,106,6,161,3,1,0,100, + 2,83,0,41,3,122,30,73,110,105,116,105,97,108,105,122, + 101,32,97,110,32,101,120,116,101,110,115,105,111,110,32,109, + 111,100,117,108,101,122,40,101,120,116,101,110,115,105,111,110, + 32,109,111,100,117,108,101,32,123,33,114,125,32,101,120,101, + 99,117,116,101,100,32,102,114,111,109,32,123,33,114,125,78, + 41,7,114,118,0,0,0,114,191,0,0,0,114,145,0,0, + 0,90,12,101,120,101,99,95,100,121,110,97,109,105,99,114, + 132,0,0,0,114,102,0,0,0,114,37,0,0,0,41,2, + 114,104,0,0,0,114,193,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,114,194,0,0,0,248,3, + 0,0,115,6,0,0,0,0,2,14,1,6,1,122,31,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,3, + 0,0,0,115,36,0,0,0,116,0,124,0,106,1,131,1, + 100,1,25,0,137,0,116,2,135,0,102,1,100,2,100,3, + 132,8,116,3,68,0,131,1,131,1,83,0,41,4,122,49, + 82,101,116,117,114,110,32,84,114,117,101,32,105,102,32,116, + 104,101,32,101,120,116,101,110,115,105,111,110,32,109,111,100, + 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, + 46,114,31,0,0,0,99,1,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,51,0,0,0,115,26,0,0,0, + 124,0,93,18,125,1,136,0,100,0,124,1,23,0,107,2, + 86,0,1,0,113,2,100,1,83,0,41,2,114,188,0,0, + 0,78,114,4,0,0,0,41,2,114,24,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,6,0,0,0,250,9,60, + 103,101,110,101,120,112,114,62,1,4,0,0,115,2,0,0, + 0,4,1,122,49,69,120,116,101,110,115,105,111,110,70,105, + 108,101,76,111,97,100,101,114,46,105,115,95,112,97,99,107, + 97,103,101,46,60,108,111,99,97,108,115,62,46,60,103,101, + 110,101,120,112,114,62,41,4,114,40,0,0,0,114,37,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,104,0, + 0,0,114,123,0,0,0,114,4,0,0,0,41,1,114,230, + 0,0,0,114,6,0,0,0,114,163,0,0,0,254,3,0, + 0,115,6,0,0,0,0,2,14,1,12,1,122,30,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,83,0,41,2,122,63,82,101, + 116,117,114,110,32,78,111,110,101,32,97,115,32,97,110,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, + 32,99,97,110,110,111,116,32,99,114,101,97,116,101,32,97, + 32,99,111,100,101,32,111,98,106,101,99,116,46,78,114,4, + 0,0,0,41,2,114,104,0,0,0,114,123,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,190, + 0,0,0,4,4,0,0,115,2,0,0,0,0,2,122,28, + 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,83,0,41,2,122,53,82,101, + 116,117,114,110,32,78,111,110,101,32,97,115,32,101,120,116, + 101,110,115,105,111,110,32,109,111,100,117,108,101,115,32,104, + 97,118,101,32,110,111,32,115,111,117,114,99,101,32,99,111, + 100,101,46,78,114,4,0,0,0,41,2,114,104,0,0,0, + 114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,114,204,0,0,0,8,4,0,0,115,2,0, + 0,0,0,2,122,30,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, + 117,114,99,101,99,2,0,0,0,0,0,0,0,2,0,0, 0,1,0,0,0,67,0,0,0,115,6,0,0,0,124,0, 106,0,83,0,41,1,122,58,82,101,116,117,114,110,32,116, 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, @@ -1268,1162 +1661,899 @@ const unsigned char _Py_M__importlib_external[] = { 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, 114,46,41,1,114,37,0,0,0,41,2,114,104,0,0,0, 114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,155,0,0,0,59,3,0,0,115,2,0, - 0,0,0,3,122,23,70,105,108,101,76,111,97,100,101,114, - 46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0, - 0,0,0,0,0,0,3,0,0,0,9,0,0,0,67,0, - 0,0,115,32,0,0,0,116,0,160,1,124,1,100,1,161, - 2,143,10,125,2,124,2,160,2,161,0,83,0,81,0,82, - 0,88,0,100,2,83,0,41,3,122,39,82,101,116,117,114, - 110,32,116,104,101,32,100,97,116,97,32,102,114,111,109,32, - 112,97,116,104,32,97,115,32,114,97,119,32,98,121,116,101, - 115,46,218,1,114,78,41,3,114,52,0,0,0,114,53,0, - 0,0,90,4,114,101,97,100,41,3,114,104,0,0,0,114, - 37,0,0,0,114,57,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,114,196,0,0,0,64,3,0, - 0,115,4,0,0,0,0,2,14,1,122,19,70,105,108,101, - 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,41, - 12,114,109,0,0,0,114,108,0,0,0,114,110,0,0,0, - 114,111,0,0,0,114,182,0,0,0,114,209,0,0,0,114, - 211,0,0,0,114,120,0,0,0,114,190,0,0,0,114,155, - 0,0,0,114,196,0,0,0,90,13,95,95,99,108,97,115, - 115,99,101,108,108,95,95,114,4,0,0,0,114,4,0,0, - 0,41,1,114,207,0,0,0,114,6,0,0,0,114,206,0, - 0,0,29,3,0,0,115,12,0,0,0,12,5,8,6,8, - 4,8,3,16,12,12,5,114,206,0,0,0,99,0,0,0, - 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, - 0,115,46,0,0,0,101,0,90,1,100,0,90,2,100,1, - 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, - 90,5,100,6,100,7,156,1,100,8,100,9,132,2,90,6, - 100,10,83,0,41,11,218,16,83,111,117,114,99,101,70,105, - 108,101,76,111,97,100,101,114,122,62,67,111,110,99,114,101, - 116,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111, - 110,32,111,102,32,83,111,117,114,99,101,76,111,97,100,101, - 114,32,117,115,105,110,103,32,116,104,101,32,102,105,108,101, - 32,115,121,115,116,101,109,46,99,2,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,67,0,0,0,115,22,0, - 0,0,116,0,124,1,131,1,125,2,124,2,106,1,124,2, - 106,2,100,1,156,2,83,0,41,2,122,33,82,101,116,117, - 114,110,32,116,104,101,32,109,101,116,97,100,97,116,97,32, - 102,111,114,32,116,104,101,32,112,97,116,104,46,41,2,114, - 130,0,0,0,114,131,0,0,0,41,3,114,41,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,104,0,0,0,114,37,0,0,0,114, - 204,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,114,193,0,0,0,74,3,0,0,115,4,0,0, - 0,0,2,8,1,122,27,83,111,117,114,99,101,70,105,108, - 101,76,111,97,100,101,114,46,112,97,116,104,95,115,116,97, - 116,115,99,4,0,0,0,0,0,0,0,5,0,0,0,5, - 0,0,0,67,0,0,0,115,24,0,0,0,116,0,124,1, - 131,1,125,4,124,0,106,1,124,2,124,3,124,4,100,1, - 141,3,83,0,41,2,78,41,1,218,5,95,109,111,100,101, - 41,2,114,101,0,0,0,114,194,0,0,0,41,5,114,104, - 0,0,0,114,94,0,0,0,114,93,0,0,0,114,56,0, - 0,0,114,44,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,195,0,0,0,79,3,0,0,115, - 4,0,0,0,0,2,8,1,122,32,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,46,95,99,97,99,104, - 101,95,98,121,116,101,99,111,100,101,105,182,1,0,0,41, - 1,114,216,0,0,0,99,3,0,0,0,1,0,0,0,9, - 0,0,0,18,0,0,0,67,0,0,0,115,248,0,0,0, - 116,0,124,1,131,1,92,2,125,4,125,5,103,0,125,6, - 120,38,124,4,114,54,116,1,124,4,131,1,115,54,116,0, - 124,4,131,1,92,2,125,4,125,7,124,6,160,2,124,7, - 161,1,1,0,113,18,87,0,120,108,116,3,124,6,131,1, - 68,0,93,96,125,7,116,4,124,4,124,7,131,2,125,4, - 121,14,116,5,160,6,124,4,161,1,1,0,87,0,113,66, - 4,0,116,7,107,10,114,116,1,0,1,0,1,0,119,66, - 89,0,113,66,4,0,116,8,107,10,114,160,1,0,125,8, - 1,0,122,18,116,9,160,10,100,1,124,4,124,8,161,3, - 1,0,100,2,83,0,100,2,125,8,126,8,88,0,113,66, - 88,0,113,66,87,0,121,28,116,11,124,1,124,2,124,3, - 131,3,1,0,116,9,160,10,100,3,124,1,161,2,1,0, - 87,0,110,48,4,0,116,8,107,10,114,242,1,0,125,8, - 1,0,122,20,116,9,160,10,100,1,124,1,124,8,161,3, - 1,0,87,0,89,0,100,2,100,2,125,8,126,8,88,0, - 110,2,88,0,100,2,83,0,41,4,122,27,87,114,105,116, - 101,32,98,121,116,101,115,32,100,97,116,97,32,116,111,32, - 97,32,102,105,108,101,46,122,27,99,111,117,108,100,32,110, - 111,116,32,99,114,101,97,116,101,32,123,33,114,125,58,32, - 123,33,114,125,78,122,12,99,114,101,97,116,101,100,32,123, - 33,114,125,41,12,114,40,0,0,0,114,48,0,0,0,114, - 161,0,0,0,114,35,0,0,0,114,30,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,42,0,0,0, - 114,118,0,0,0,114,133,0,0,0,114,58,0,0,0,41, - 9,114,104,0,0,0,114,37,0,0,0,114,56,0,0,0, - 114,216,0,0,0,218,6,112,97,114,101,110,116,114,98,0, - 0,0,114,29,0,0,0,114,25,0,0,0,114,197,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 114,194,0,0,0,84,3,0,0,115,42,0,0,0,0,2, - 12,1,4,2,14,1,12,1,14,2,14,1,10,1,2,1, - 14,1,14,2,6,1,16,3,6,1,8,1,20,1,2,1, - 12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,46,115,101,116,95,100, - 97,116,97,78,41,7,114,109,0,0,0,114,108,0,0,0, - 114,110,0,0,0,114,111,0,0,0,114,193,0,0,0,114, - 195,0,0,0,114,194,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,214,0, - 0,0,70,3,0,0,115,6,0,0,0,12,4,8,5,8, - 5,114,214,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,64,0,0,0,115,32,0,0,0, - 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, - 132,0,90,4,100,4,100,5,132,0,90,5,100,6,83,0, - 41,7,218,20,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,122,45,76,111,97,100,101,114, - 32,119,104,105,99,104,32,104,97,110,100,108,101,115,32,115, - 111,117,114,99,101,108,101,115,115,32,102,105,108,101,32,105, - 109,112,111,114,116,115,46,99,2,0,0,0,0,0,0,0, - 5,0,0,0,5,0,0,0,67,0,0,0,115,48,0,0, - 0,124,0,160,0,124,1,161,1,125,2,124,0,160,1,124, - 2,161,1,125,3,116,2,124,3,124,1,124,2,100,1,141, - 3,125,4,116,3,124,4,124,1,124,2,100,2,141,3,83, - 0,41,3,78,41,2,114,102,0,0,0,114,37,0,0,0, - 41,2,114,102,0,0,0,114,93,0,0,0,41,4,114,155, - 0,0,0,114,196,0,0,0,114,139,0,0,0,114,145,0, - 0,0,41,5,114,104,0,0,0,114,123,0,0,0,114,37, - 0,0,0,114,56,0,0,0,114,205,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,184,0,0, - 0,119,3,0,0,115,8,0,0,0,0,1,10,1,10,1, - 14,1,122,29,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,122,39,82,101,116,117,114,110,32,78,111,110,101,32,97, - 115,32,116,104,101,114,101,32,105,115,32,110,111,32,115,111, - 117,114,99,101,32,99,111,100,101,46,78,114,4,0,0,0, - 41,2,114,104,0,0,0,114,123,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,114,198,0,0,0, - 125,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, - 109,0,0,0,114,108,0,0,0,114,110,0,0,0,114,111, - 0,0,0,114,184,0,0,0,114,198,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,219,0,0,0,115,3,0,0,115,4,0,0,0,12, - 4,8,6,114,219,0,0,0,99,0,0,0,0,0,0,0, - 0,0,0,0,0,3,0,0,0,64,0,0,0,115,92,0, + 6,0,0,0,114,161,0,0,0,12,4,0,0,115,2,0, + 0,0,0,3,122,32,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,103,101,116,95,102,105, + 108,101,110,97,109,101,78,41,14,114,109,0,0,0,114,108, + 0,0,0,114,110,0,0,0,114,111,0,0,0,114,188,0, + 0,0,114,217,0,0,0,114,219,0,0,0,114,189,0,0, + 0,114,194,0,0,0,114,163,0,0,0,114,190,0,0,0, + 114,204,0,0,0,114,120,0,0,0,114,161,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,114,228,0,0,0,221,3,0,0,115,18,0,0, + 0,12,8,8,4,8,4,8,3,8,8,8,6,8,6,8, + 4,8,4,114,228,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,64,0,0,0,115,96,0, 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, 100,3,132,0,90,4,100,4,100,5,132,0,90,5,100,6, 100,7,132,0,90,6,100,8,100,9,132,0,90,7,100,10, 100,11,132,0,90,8,100,12,100,13,132,0,90,9,100,14, - 100,15,132,0,90,10,100,16,100,17,132,0,90,11,101,12, - 100,18,100,19,132,0,131,1,90,13,100,20,83,0,41,21, - 218,19,69,120,116,101,110,115,105,111,110,70,105,108,101,76, - 111,97,100,101,114,122,93,76,111,97,100,101,114,32,102,111, - 114,32,101,120,116,101,110,115,105,111,110,32,109,111,100,117, - 108,101,115,46,10,10,32,32,32,32,84,104,101,32,99,111, - 110,115,116,114,117,99,116,111,114,32,105,115,32,100,101,115, - 105,103,110,101,100,32,116,111,32,119,111,114,107,32,119,105, - 116,104,32,70,105,108,101,70,105,110,100,101,114,46,10,10, - 32,32,32,32,99,3,0,0,0,0,0,0,0,3,0,0, - 0,2,0,0,0,67,0,0,0,115,16,0,0,0,124,1, - 124,0,95,0,124,2,124,0,95,1,100,0,83,0,41,1, - 78,41,2,114,102,0,0,0,114,37,0,0,0,41,3,114, - 104,0,0,0,114,102,0,0,0,114,37,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,182,0, - 0,0,142,3,0,0,115,4,0,0,0,0,1,6,1,122, - 28,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,95,95,105,110,105,116,95,95,99,2,0, - 0,0,0,0,0,0,2,0,0,0,2,0,0,0,67,0, - 0,0,115,24,0,0,0,124,0,106,0,124,1,106,0,107, - 2,111,22,124,0,106,1,124,1,106,1,107,2,83,0,41, - 1,78,41,2,114,207,0,0,0,114,115,0,0,0,41,2, - 114,104,0,0,0,114,208,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,209,0,0,0,146,3, - 0,0,115,4,0,0,0,0,1,12,1,122,26,69,120,116, - 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, - 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0, - 0,116,0,124,0,106,1,131,1,116,0,124,0,106,2,131, - 1,65,0,83,0,41,1,78,41,3,114,210,0,0,0,114, - 102,0,0,0,114,37,0,0,0,41,1,114,104,0,0,0, + 100,15,132,0,90,10,100,16,100,17,132,0,90,11,100,18, + 100,19,132,0,90,12,100,20,100,21,132,0,90,13,100,22, + 83,0,41,23,218,14,95,78,97,109,101,115,112,97,99,101, + 80,97,116,104,97,38,1,0,0,82,101,112,114,101,115,101, + 110,116,115,32,97,32,110,97,109,101,115,112,97,99,101,32, + 112,97,99,107,97,103,101,39,115,32,112,97,116,104,46,32, + 32,73,116,32,117,115,101,115,32,116,104,101,32,109,111,100, + 117,108,101,32,110,97,109,101,10,32,32,32,32,116,111,32, + 102,105,110,100,32,105,116,115,32,112,97,114,101,110,116,32, + 109,111,100,117,108,101,44,32,97,110,100,32,102,114,111,109, + 32,116,104,101,114,101,32,105,116,32,108,111,111,107,115,32, + 117,112,32,116,104,101,32,112,97,114,101,110,116,39,115,10, + 32,32,32,32,95,95,112,97,116,104,95,95,46,32,32,87, + 104,101,110,32,116,104,105,115,32,99,104,97,110,103,101,115, + 44,32,116,104,101,32,109,111,100,117,108,101,39,115,32,111, + 119,110,32,112,97,116,104,32,105,115,32,114,101,99,111,109, + 112,117,116,101,100,44,10,32,32,32,32,117,115,105,110,103, + 32,112,97,116,104,95,102,105,110,100,101,114,46,32,32,70, + 111,114,32,116,111,112,45,108,101,118,101,108,32,109,111,100, + 117,108,101,115,44,32,116,104,101,32,112,97,114,101,110,116, + 32,109,111,100,117,108,101,39,115,32,112,97,116,104,10,32, + 32,32,32,105,115,32,115,121,115,46,112,97,116,104,46,99, + 4,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, + 67,0,0,0,115,36,0,0,0,124,1,124,0,95,0,124, + 2,124,0,95,1,116,2,124,0,160,3,161,0,131,1,124, + 0,95,4,124,3,124,0,95,5,100,0,83,0,41,1,78, + 41,6,218,5,95,110,97,109,101,218,5,95,112,97,116,104, + 114,97,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,104,0,0,0,114, + 102,0,0,0,114,37,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,6,0,0,0,114,188,0,0,0,25,4,0,0,115,8, + 0,0,0,0,1,6,1,6,1,14,1,122,23,95,78,97, + 109,101,115,112,97,99,101,80,97,116,104,46,95,95,105,110, + 105,116,95,95,99,1,0,0,0,0,0,0,0,4,0,0, + 0,3,0,0,0,67,0,0,0,115,38,0,0,0,124,0, + 106,0,160,1,100,1,161,1,92,3,125,1,125,2,125,3, + 124,2,100,2,107,2,114,30,100,6,83,0,124,1,100,5, + 102,2,83,0,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,61,0,0,0,114,32,0,0,0, + 114,8,0,0,0,114,37,0,0,0,90,8,95,95,112,97, + 116,104,95,95,41,2,114,8,0,0,0,114,37,0,0,0, + 41,2,114,235,0,0,0,114,34,0,0,0,41,4,114,104, + 0,0,0,114,226,0,0,0,218,3,100,111,116,90,2,109, + 101,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, + 218,23,95,102,105,110,100,95,112,97,114,101,110,116,95,112, + 97,116,104,95,110,97,109,101,115,31,4,0,0,115,8,0, + 0,0,0,2,18,1,8,2,4,3,122,38,95,78,97,109, + 101,115,112,97,99,101,80,97,116,104,46,95,102,105,110,100, + 95,112,97,114,101,110,116,95,112,97,116,104,95,110,97,109, + 101,115,99,1,0,0,0,0,0,0,0,3,0,0,0,3, + 0,0,0,67,0,0,0,115,28,0,0,0,124,0,160,0, + 161,0,92,2,125,1,125,2,116,1,116,2,106,3,124,1, + 25,0,124,2,131,2,83,0,41,1,78,41,4,114,242,0, + 0,0,114,114,0,0,0,114,8,0,0,0,218,7,109,111, + 100,117,108,101,115,41,3,114,104,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,6,0,0,0,114, - 211,0,0,0,150,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,5,0,0,0,67,0, - 0,0,115,36,0,0,0,116,0,160,1,116,2,106,3,124, - 1,161,2,125,2,116,0,160,4,100,1,124,1,106,5,124, - 0,106,6,161,3,1,0,124,2,83,0,41,2,122,38,67, - 114,101,97,116,101,32,97,110,32,117,110,105,116,105,97,108, - 105,122,101,100,32,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,122,38,101,120,116,101,110,115,105,111,110, - 32,109,111,100,117,108,101,32,123,33,114,125,32,108,111,97, - 100,101,100,32,102,114,111,109,32,123,33,114,125,41,7,114, - 118,0,0,0,114,185,0,0,0,114,143,0,0,0,90,14, - 99,114,101,97,116,101,95,100,121,110,97,109,105,99,114,133, - 0,0,0,114,102,0,0,0,114,37,0,0,0,41,3,114, - 104,0,0,0,114,162,0,0,0,114,187,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,183,0, - 0,0,153,3,0,0,115,10,0,0,0,0,2,4,1,10, - 1,6,1,12,1,122,33,69,120,116,101,110,115,105,111,110, - 70,105,108,101,76,111,97,100,101,114,46,99,114,101,97,116, - 101,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, - 0,2,0,0,0,5,0,0,0,67,0,0,0,115,36,0, - 0,0,116,0,160,1,116,2,106,3,124,1,161,2,1,0, - 116,0,160,4,100,1,124,0,106,5,124,0,106,6,161,3, - 1,0,100,2,83,0,41,3,122,30,73,110,105,116,105,97, - 108,105,122,101,32,97,110,32,101,120,116,101,110,115,105,111, - 110,32,109,111,100,117,108,101,122,40,101,120,116,101,110,115, - 105,111,110,32,109,111,100,117,108,101,32,123,33,114,125,32, - 101,120,101,99,117,116,101,100,32,102,114,111,109,32,123,33, - 114,125,78,41,7,114,118,0,0,0,114,185,0,0,0,114, - 143,0,0,0,90,12,101,120,101,99,95,100,121,110,97,109, - 105,99,114,133,0,0,0,114,102,0,0,0,114,37,0,0, - 0,41,2,114,104,0,0,0,114,187,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,188,0,0, - 0,161,3,0,0,115,6,0,0,0,0,2,14,1,6,1, - 122,31,69,120,116,101,110,115,105,111,110,70,105,108,101,76, - 111,97,100,101,114,46,101,120,101,99,95,109,111,100,117,108, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,3,0,0,0,115,36,0,0,0,116,0,124,0,106, - 1,131,1,100,1,25,0,137,0,116,2,135,0,102,1,100, - 2,100,3,132,8,116,3,68,0,131,1,131,1,83,0,41, - 4,122,49,82,101,116,117,114,110,32,84,114,117,101,32,105, - 102,32,116,104,101,32,101,120,116,101,110,115,105,111,110,32, - 109,111,100,117,108,101,32,105,115,32,97,32,112,97,99,107, - 97,103,101,46,114,31,0,0,0,99,1,0,0,0,0,0, - 0,0,2,0,0,0,4,0,0,0,51,0,0,0,115,26, - 0,0,0,124,0,93,18,125,1,136,0,100,0,124,1,23, - 0,107,2,86,0,1,0,113,2,100,1,83,0,41,2,114, - 182,0,0,0,78,114,4,0,0,0,41,2,114,24,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,6,0,0,0, - 250,9,60,103,101,110,101,120,112,114,62,170,3,0,0,115, - 2,0,0,0,4,1,122,49,69,120,116,101,110,115,105,111, - 110,70,105,108,101,76,111,97,100,101,114,46,105,115,95,112, - 97,99,107,97,103,101,46,60,108,111,99,97,108,115,62,46, - 60,103,101,110,101,120,112,114,62,41,4,114,40,0,0,0, - 114,37,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,104,0,0,0,114,123,0,0,0,114,4,0,0,0,41, - 1,114,222,0,0,0,114,6,0,0,0,114,157,0,0,0, - 167,3,0,0,115,6,0,0,0,0,2,14,1,12,1,122, - 30,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,105,115,95,112,97,99,107,97,103,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,122, - 63,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, - 97,110,32,101,120,116,101,110,115,105,111,110,32,109,111,100, - 117,108,101,32,99,97,110,110,111,116,32,99,114,101,97,116, - 101,32,97,32,99,111,100,101,32,111,98,106,101,99,116,46, - 78,114,4,0,0,0,41,2,114,104,0,0,0,114,123,0, + 237,0,0,0,41,4,0,0,115,4,0,0,0,0,1,12, + 1,122,31,95,78,97,109,101,115,112,97,99,101,80,97,116, + 104,46,95,103,101,116,95,112,97,114,101,110,116,95,112,97, + 116,104,99,1,0,0,0,0,0,0,0,3,0,0,0,4, + 0,0,0,67,0,0,0,115,80,0,0,0,116,0,124,0, + 160,1,161,0,131,1,125,1,124,1,124,0,106,2,107,3, + 114,74,124,0,160,3,124,0,106,4,124,1,161,2,125,2, + 124,2,100,0,107,9,114,68,124,2,106,5,100,0,107,8, + 114,68,124,2,106,6,114,68,124,2,106,6,124,0,95,7, + 124,1,124,0,95,2,124,0,106,7,83,0,41,1,78,41, + 8,114,97,0,0,0,114,237,0,0,0,114,238,0,0,0, + 114,239,0,0,0,114,235,0,0,0,114,124,0,0,0,114, + 160,0,0,0,114,236,0,0,0,41,3,114,104,0,0,0, + 90,11,112,97,114,101,110,116,95,112,97,116,104,114,168,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,184,0,0,0,173,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,83,0,41,2,122, - 53,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, - 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 115,32,104,97,118,101,32,110,111,32,115,111,117,114,99,101, - 32,99,111,100,101,46,78,114,4,0,0,0,41,2,114,104, - 0,0,0,114,123,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,114,198,0,0,0,177,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,6,0,0, - 0,124,0,106,0,83,0,41,1,122,58,82,101,116,117,114, - 110,32,116,104,101,32,112,97,116,104,32,116,111,32,116,104, - 101,32,115,111,117,114,99,101,32,102,105,108,101,32,97,115, - 32,102,111,117,110,100,32,98,121,32,116,104,101,32,102,105, - 110,100,101,114,46,41,1,114,37,0,0,0,41,2,114,104, - 0,0,0,114,123,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,114,155,0,0,0,181,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,109,0,0, - 0,114,108,0,0,0,114,110,0,0,0,114,111,0,0,0, - 114,182,0,0,0,114,209,0,0,0,114,211,0,0,0,114, - 183,0,0,0,114,188,0,0,0,114,157,0,0,0,114,184, - 0,0,0,114,198,0,0,0,114,120,0,0,0,114,155,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,220,0,0,0,134,3,0,0,115, - 18,0,0,0,12,8,8,4,8,4,8,3,8,8,8,6, - 8,6,8,4,8,4,114,220,0,0,0,99,0,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0, - 115,96,0,0,0,101,0,90,1,100,0,90,2,100,1,90, - 3,100,2,100,3,132,0,90,4,100,4,100,5,132,0,90, - 5,100,6,100,7,132,0,90,6,100,8,100,9,132,0,90, - 7,100,10,100,11,132,0,90,8,100,12,100,13,132,0,90, - 9,100,14,100,15,132,0,90,10,100,16,100,17,132,0,90, - 11,100,18,100,19,132,0,90,12,100,20,100,21,132,0,90, - 13,100,22,83,0,41,23,218,14,95,78,97,109,101,115,112, - 97,99,101,80,97,116,104,97,38,1,0,0,82,101,112,114, - 101,115,101,110,116,115,32,97,32,110,97,109,101,115,112,97, - 99,101,32,112,97,99,107,97,103,101,39,115,32,112,97,116, - 104,46,32,32,73,116,32,117,115,101,115,32,116,104,101,32, - 109,111,100,117,108,101,32,110,97,109,101,10,32,32,32,32, - 116,111,32,102,105,110,100,32,105,116,115,32,112,97,114,101, - 110,116,32,109,111,100,117,108,101,44,32,97,110,100,32,102, - 114,111,109,32,116,104,101,114,101,32,105,116,32,108,111,111, - 107,115,32,117,112,32,116,104,101,32,112,97,114,101,110,116, - 39,115,10,32,32,32,32,95,95,112,97,116,104,95,95,46, - 32,32,87,104,101,110,32,116,104,105,115,32,99,104,97,110, - 103,101,115,44,32,116,104,101,32,109,111,100,117,108,101,39, - 115,32,111,119,110,32,112,97,116,104,32,105,115,32,114,101, - 99,111,109,112,117,116,101,100,44,10,32,32,32,32,117,115, - 105,110,103,32,112,97,116,104,95,102,105,110,100,101,114,46, - 32,32,70,111,114,32,116,111,112,45,108,101,118,101,108,32, - 109,111,100,117,108,101,115,44,32,116,104,101,32,112,97,114, - 101,110,116,32,109,111,100,117,108,101,39,115,32,112,97,116, - 104,10,32,32,32,32,105,115,32,115,121,115,46,112,97,116, - 104,46,99,4,0,0,0,0,0,0,0,4,0,0,0,3, - 0,0,0,67,0,0,0,115,36,0,0,0,124,1,124,0, - 95,0,124,2,124,0,95,1,116,2,124,0,160,3,161,0, - 131,1,124,0,95,4,124,3,124,0,95,5,100,0,83,0, - 41,1,78,41,6,218,5,95,110,97,109,101,218,5,95,112, - 97,116,104,114,97,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,104,0, - 0,0,114,102,0,0,0,114,37,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,6,0,0,0,114,182,0,0,0,194,3,0, - 0,115,8,0,0,0,0,1,6,1,6,1,14,1,122,23, - 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, - 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, - 4,0,0,0,3,0,0,0,67,0,0,0,115,38,0,0, - 0,124,0,106,0,160,1,100,1,161,1,92,3,125,1,125, - 2,125,3,124,2,100,2,107,2,114,30,100,6,83,0,124, - 1,100,5,102,2,83,0,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,61,0,0,0,114,32, - 0,0,0,114,8,0,0,0,114,37,0,0,0,90,8,95, - 95,112,97,116,104,95,95,41,2,114,8,0,0,0,114,37, - 0,0,0,41,2,114,227,0,0,0,114,34,0,0,0,41, - 4,114,104,0,0,0,114,218,0,0,0,218,3,100,111,116, - 90,2,109,101,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,218,23,95,102,105,110,100,95,112,97,114,101,110, - 116,95,112,97,116,104,95,110,97,109,101,115,200,3,0,0, - 115,8,0,0,0,0,2,18,1,8,2,4,3,122,38,95, - 78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,102, - 105,110,100,95,112,97,114,101,110,116,95,112,97,116,104,95, - 110,97,109,101,115,99,1,0,0,0,0,0,0,0,3,0, - 0,0,3,0,0,0,67,0,0,0,115,28,0,0,0,124, - 0,160,0,161,0,92,2,125,1,125,2,116,1,116,2,106, - 3,124,1,25,0,124,2,131,2,83,0,41,1,78,41,4, - 114,234,0,0,0,114,114,0,0,0,114,8,0,0,0,218, - 7,109,111,100,117,108,101,115,41,3,114,104,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,6,0, - 0,0,114,229,0,0,0,210,3,0,0,115,4,0,0,0, - 0,1,12,1,122,31,95,78,97,109,101,115,112,97,99,101, - 80,97,116,104,46,95,103,101,116,95,112,97,114,101,110,116, - 95,112,97,116,104,99,1,0,0,0,0,0,0,0,3,0, - 0,0,4,0,0,0,67,0,0,0,115,80,0,0,0,116, - 0,124,0,160,1,161,0,131,1,125,1,124,1,124,0,106, - 2,107,3,114,74,124,0,160,3,124,0,106,4,124,1,161, - 2,125,2,124,2,100,0,107,9,114,68,124,2,106,5,100, - 0,107,8,114,68,124,2,106,6,114,68,124,2,106,6,124, - 0,95,7,124,1,124,0,95,2,124,0,106,7,83,0,41, - 1,78,41,8,114,97,0,0,0,114,229,0,0,0,114,230, - 0,0,0,114,231,0,0,0,114,227,0,0,0,114,124,0, - 0,0,114,154,0,0,0,114,228,0,0,0,41,3,114,104, - 0,0,0,90,11,112,97,114,101,110,116,95,112,97,116,104, - 114,162,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,12,95,114,101,99,97,108,99,117,108,97, - 116,101,214,3,0,0,115,16,0,0,0,0,2,12,1,10, - 1,14,3,18,1,6,1,8,1,6,1,122,27,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,95,114,101,99, - 97,108,99,117,108,97,116,101,99,1,0,0,0,0,0,0, - 0,1,0,0,0,3,0,0,0,67,0,0,0,115,12,0, - 0,0,116,0,124,0,160,1,161,0,131,1,83,0,41,1, - 78,41,2,218,4,105,116,101,114,114,236,0,0,0,41,1, - 114,104,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,8,95,95,105,116,101,114,95,95,227,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,3,0,0,0,0,0,0,0,3,0,0,0,3, - 0,0,0,67,0,0,0,115,14,0,0,0,124,2,124,0, - 106,0,124,1,60,0,100,0,83,0,41,1,78,41,1,114, - 228,0,0,0,41,3,114,104,0,0,0,218,5,105,110,100, - 101,120,114,37,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,11,95,95,115,101,116,105,116,101, - 109,95,95,230,3,0,0,115,2,0,0,0,0,1,122,26, - 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, - 95,115,101,116,105,116,101,109,95,95,99,1,0,0,0,0, - 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,115, - 12,0,0,0,116,0,124,0,160,1,161,0,131,1,83,0, - 41,1,78,41,2,114,33,0,0,0,114,236,0,0,0,41, - 1,114,104,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,7,95,95,108,101,110,95,95,233,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,3,0, - 0,0,67,0,0,0,115,12,0,0,0,100,1,160,0,124, - 0,106,1,161,1,83,0,41,2,78,122,20,95,78,97,109, - 101,115,112,97,99,101,80,97,116,104,40,123,33,114,125,41, - 41,2,114,50,0,0,0,114,228,0,0,0,41,1,114,104, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,218,8,95,95,114,101,112,114,95,95,236,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,3,0,0, - 0,67,0,0,0,115,12,0,0,0,124,1,124,0,160,0, - 161,0,107,6,83,0,41,1,78,41,1,114,236,0,0,0, - 41,2,114,104,0,0,0,218,4,105,116,101,109,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,218,12,95,95, - 99,111,110,116,97,105,110,115,95,95,239,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,3, - 0,0,0,67,0,0,0,115,16,0,0,0,124,0,106,0, - 160,1,124,1,161,1,1,0,100,0,83,0,41,1,78,41, - 2,114,228,0,0,0,114,161,0,0,0,41,2,114,104,0, - 0,0,114,243,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,161,0,0,0,242,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,14, - 114,109,0,0,0,114,108,0,0,0,114,110,0,0,0,114, - 111,0,0,0,114,182,0,0,0,114,234,0,0,0,114,229, - 0,0,0,114,236,0,0,0,114,238,0,0,0,114,240,0, - 0,0,114,241,0,0,0,114,242,0,0,0,114,244,0,0, - 0,114,161,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,114,226,0,0,0,187, - 3,0,0,115,20,0,0,0,12,7,8,6,8,10,8,4, - 8,13,8,3,8,3,8,3,8,3,8,3,114,226,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,3,0, - 0,0,64,0,0,0,115,80,0,0,0,101,0,90,1,100, - 0,90,2,100,1,100,2,132,0,90,3,101,4,100,3,100, - 4,132,0,131,1,90,5,100,5,100,6,132,0,90,6,100, - 7,100,8,132,0,90,7,100,9,100,10,132,0,90,8,100, - 11,100,12,132,0,90,9,100,13,100,14,132,0,90,10,100, - 15,100,16,132,0,90,11,100,17,83,0,41,18,218,16,95, - 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,99, - 4,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, - 67,0,0,0,115,18,0,0,0,116,0,124,1,124,2,124, - 3,131,3,124,0,95,1,100,0,83,0,41,1,78,41,2, - 114,226,0,0,0,114,228,0,0,0,41,4,114,104,0,0, - 0,114,102,0,0,0,114,37,0,0,0,114,232,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, - 182,0,0,0,248,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,3,0,0,0,67,0,0,0,115, - 12,0,0,0,100,1,160,0,124,1,106,1,161,1,83,0, - 41,2,122,115,82,101,116,117,114,110,32,114,101,112,114,32, - 102,111,114,32,116,104,101,32,109,111,100,117,108,101,46,10, - 10,32,32,32,32,32,32,32,32,84,104,101,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,84,104,101,32,105,109,112,111,114,116,32,109, - 97,99,104,105,110,101,114,121,32,100,111,101,115,32,116,104, - 101,32,106,111,98,32,105,116,115,101,108,102,46,10,10,32, - 32,32,32,32,32,32,32,122,25,60,109,111,100,117,108,101, - 32,123,33,114,125,32,40,110,97,109,101,115,112,97,99,101, - 41,62,41,2,114,50,0,0,0,114,109,0,0,0,41,2, - 114,168,0,0,0,114,187,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,218,11,109,111,100,117,108, - 101,95,114,101,112,114,251,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,83,0,41,2,78, - 84,114,4,0,0,0,41,2,114,104,0,0,0,114,123,0, + 0,218,12,95,114,101,99,97,108,99,117,108,97,116,101,45, + 4,0,0,115,16,0,0,0,0,2,12,1,10,1,14,3, + 18,1,6,1,8,1,6,1,122,27,95,78,97,109,101,115, + 112,97,99,101,80,97,116,104,46,95,114,101,99,97,108,99, + 117,108,97,116,101,99,1,0,0,0,0,0,0,0,1,0, + 0,0,3,0,0,0,67,0,0,0,115,12,0,0,0,116, + 0,124,0,160,1,161,0,131,1,83,0,41,1,78,41,2, + 218,4,105,116,101,114,114,244,0,0,0,41,1,114,104,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,157,0,0,0,4,4,0,0,115,2,0,0,0,0, - 1,122,27,95,78,97,109,101,115,112,97,99,101,76,111,97, - 100,101,114,46,105,115,95,112,97,99,107,97,103,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, - 0,0,0,115,4,0,0,0,100,1,83,0,41,2,78,114, - 32,0,0,0,114,4,0,0,0,41,2,114,104,0,0,0, - 114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,198,0,0,0,7,4,0,0,115,2,0, - 0,0,0,1,122,27,95,78,97,109,101,115,112,97,99,101, - 76,111,97,100,101,114,46,103,101,116,95,115,111,117,114,99, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,6,0, - 0,0,67,0,0,0,115,16,0,0,0,116,0,100,1,100, - 2,100,3,100,4,100,5,141,4,83,0,41,6,78,114,32, - 0,0,0,122,8,60,115,116,114,105,110,103,62,114,186,0, - 0,0,84,41,1,114,200,0,0,0,41,1,114,201,0,0, - 0,41,2,114,104,0,0,0,114,123,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,184,0,0, - 0,10,4,0,0,115,2,0,0,0,0,1,122,25,95,78, - 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,103, - 101,116,95,99,111,100,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, - 0,100,1,83,0,41,2,122,42,85,115,101,32,100,101,102, - 97,117,108,116,32,115,101,109,97,110,116,105,99,115,32,102, - 111,114,32,109,111,100,117,108,101,32,99,114,101,97,116,105, - 111,110,46,78,114,4,0,0,0,41,2,114,104,0,0,0, - 114,162,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,183,0,0,0,13,4,0,0,115,0,0, - 0,0,122,30,95,78,97,109,101,115,112,97,99,101,76,111, - 97,100,101,114,46,99,114,101,97,116,101,95,109,111,100,117, - 108,101,99,2,0,0,0,0,0,0,0,2,0,0,0,1, - 0,0,0,67,0,0,0,115,4,0,0,0,100,0,83,0, - 41,1,78,114,4,0,0,0,41,2,114,104,0,0,0,114, - 187,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,114,188,0,0,0,16,4,0,0,115,2,0,0, - 0,0,1,122,28,95,78,97,109,101,115,112,97,99,101,76, - 111,97,100,101,114,46,101,120,101,99,95,109,111,100,117,108, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,67,0,0,0,115,26,0,0,0,116,0,160,1,100, - 1,124,0,106,2,161,2,1,0,116,0,160,3,124,0,124, - 1,161,2,83,0,41,2,122,98,76,111,97,100,32,97,32, - 110,97,109,101,115,112,97,99,101,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,32,32,32,32,84,104,105,115,32, - 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, - 97,116,101,100,46,32,32,85,115,101,32,101,120,101,99,95, - 109,111,100,117,108,101,40,41,32,105,110,115,116,101,97,100, - 46,10,10,32,32,32,32,32,32,32,32,122,38,110,97,109, - 101,115,112,97,99,101,32,109,111,100,117,108,101,32,108,111, - 97,100,101,100,32,119,105,116,104,32,112,97,116,104,32,123, - 33,114,125,41,4,114,118,0,0,0,114,133,0,0,0,114, - 228,0,0,0,114,189,0,0,0,41,2,114,104,0,0,0, - 114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,190,0,0,0,19,4,0,0,115,6,0, - 0,0,0,7,6,1,8,1,122,28,95,78,97,109,101,115, - 112,97,99,101,76,111,97,100,101,114,46,108,111,97,100,95, - 109,111,100,117,108,101,78,41,12,114,109,0,0,0,114,108, - 0,0,0,114,110,0,0,0,114,182,0,0,0,114,180,0, - 0,0,114,246,0,0,0,114,157,0,0,0,114,198,0,0, - 0,114,184,0,0,0,114,183,0,0,0,114,188,0,0,0, - 114,190,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,245,0,0,0,247,3, - 0,0,115,16,0,0,0,8,1,8,3,12,9,8,3,8, - 3,8,3,8,3,8,3,114,245,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,90,1,100,0,90,2,100,1, - 90,3,101,4,100,2,100,3,132,0,131,1,90,5,101,4, - 100,4,100,5,132,0,131,1,90,6,101,4,100,6,100,7, - 132,0,131,1,90,7,101,4,100,8,100,9,132,0,131,1, - 90,8,101,4,100,17,100,11,100,12,132,1,131,1,90,9, - 101,4,100,18,100,13,100,14,132,1,131,1,90,10,101,4, - 100,19,100,15,100,16,132,1,131,1,90,11,100,10,83,0, - 41,20,218,10,80,97,116,104,70,105,110,100,101,114,122,62, - 77,101,116,97,32,112,97,116,104,32,102,105,110,100,101,114, - 32,102,111,114,32,115,121,115,46,112,97,116,104,32,97,110, - 100,32,112,97,99,107,97,103,101,32,95,95,112,97,116,104, - 95,95,32,97,116,116,114,105,98,117,116,101,115,46,99,1, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, - 0,0,0,115,42,0,0,0,120,36,116,0,106,1,160,2, - 161,0,68,0,93,22,125,1,116,3,124,1,100,1,131,2, - 114,12,124,1,160,4,161,0,1,0,113,12,87,0,100,2, - 83,0,41,3,122,125,67,97,108,108,32,116,104,101,32,105, - 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, - 40,41,32,109,101,116,104,111,100,32,111,110,32,97,108,108, - 32,112,97,116,104,32,101,110,116,114,121,32,102,105,110,100, - 101,114,115,10,32,32,32,32,32,32,32,32,115,116,111,114, - 101,100,32,105,110,32,115,121,115,46,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,115,32,40, - 119,104,101,114,101,32,105,109,112,108,101,109,101,110,116,101, - 100,41,46,218,17,105,110,118,97,108,105,100,97,116,101,95, - 99,97,99,104,101,115,78,41,5,114,8,0,0,0,218,19, - 112,97,116,104,95,105,109,112,111,114,116,101,114,95,99,97, - 99,104,101,218,6,118,97,108,117,101,115,114,112,0,0,0, - 114,248,0,0,0,41,2,114,168,0,0,0,218,6,102,105, - 110,100,101,114,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,114,248,0,0,0,37,4,0,0,115,6,0,0, - 0,0,4,16,1,10,1,122,28,80,97,116,104,70,105,110, - 100,101,114,46,105,110,118,97,108,105,100,97,116,101,95,99, - 97,99,104,101,115,99,2,0,0,0,0,0,0,0,3,0, - 0,0,12,0,0,0,67,0,0,0,115,84,0,0,0,116, - 0,106,1,100,1,107,9,114,28,116,0,106,1,115,28,116, - 2,160,3,100,2,116,4,161,2,1,0,120,50,116,0,106, - 1,68,0,93,36,125,2,121,8,124,2,124,1,131,1,83, - 0,4,0,116,5,107,10,114,70,1,0,1,0,1,0,119, - 36,89,0,113,36,88,0,113,36,87,0,100,1,83,0,100, - 1,83,0,41,3,122,46,83,101,97,114,99,104,32,115,121, - 115,46,112,97,116,104,95,104,111,111,107,115,32,102,111,114, - 32,97,32,102,105,110,100,101,114,32,102,111,114,32,39,112, - 97,116,104,39,46,78,122,23,115,121,115,46,112,97,116,104, - 95,104,111,111,107,115,32,105,115,32,101,109,112,116,121,41, - 6,114,8,0,0,0,218,10,112,97,116,104,95,104,111,111, - 107,115,114,63,0,0,0,114,64,0,0,0,114,122,0,0, - 0,114,103,0,0,0,41,3,114,168,0,0,0,114,37,0, - 0,0,90,4,104,111,111,107,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,218,11,95,112,97,116,104,95,104, - 111,111,107,115,45,4,0,0,115,16,0,0,0,0,3,16, - 1,12,1,12,1,2,1,8,1,14,1,12,2,122,22,80, - 97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95, - 104,111,111,107,115,99,2,0,0,0,0,0,0,0,3,0, - 0,0,19,0,0,0,67,0,0,0,115,102,0,0,0,124, - 1,100,1,107,2,114,42,121,12,116,0,160,1,161,0,125, - 1,87,0,110,20,4,0,116,2,107,10,114,40,1,0,1, - 0,1,0,100,2,83,0,88,0,121,14,116,3,106,4,124, - 1,25,0,125,2,87,0,110,40,4,0,116,5,107,10,114, - 96,1,0,1,0,1,0,124,0,160,6,124,1,161,1,125, - 2,124,2,116,3,106,4,124,1,60,0,89,0,110,2,88, - 0,124,2,83,0,41,3,122,210,71,101,116,32,116,104,101, - 32,102,105,110,100,101,114,32,102,111,114,32,116,104,101,32, - 112,97,116,104,32,101,110,116,114,121,32,102,114,111,109,32, - 115,121,115,46,112,97,116,104,95,105,109,112,111,114,116,101, - 114,95,99,97,99,104,101,46,10,10,32,32,32,32,32,32, - 32,32,73,102,32,116,104,101,32,112,97,116,104,32,101,110, - 116,114,121,32,105,115,32,110,111,116,32,105,110,32,116,104, - 101,32,99,97,99,104,101,44,32,102,105,110,100,32,116,104, - 101,32,97,112,112,114,111,112,114,105,97,116,101,32,102,105, - 110,100,101,114,10,32,32,32,32,32,32,32,32,97,110,100, - 32,99,97,99,104,101,32,105,116,46,32,73,102,32,110,111, - 32,102,105,110,100,101,114,32,105,115,32,97,118,97,105,108, - 97,98,108,101,44,32,115,116,111,114,101,32,78,111,110,101, - 46,10,10,32,32,32,32,32,32,32,32,114,32,0,0,0, - 78,41,7,114,3,0,0,0,114,47,0,0,0,218,17,70, - 105,108,101,78,111,116,70,111,117,110,100,69,114,114,111,114, - 114,8,0,0,0,114,249,0,0,0,114,135,0,0,0,114, - 253,0,0,0,41,3,114,168,0,0,0,114,37,0,0,0, - 114,251,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,20,95,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,58,4,0,0,115,22, - 0,0,0,0,8,8,1,2,1,12,1,14,3,6,1,2, - 1,14,1,14,1,10,1,16,1,122,31,80,97,116,104,70, - 105,110,100,101,114,46,95,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,99,3,0,0,0,0, - 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, - 82,0,0,0,116,0,124,2,100,1,131,2,114,26,124,2, - 160,1,124,1,161,1,92,2,125,3,125,4,110,14,124,2, - 160,2,124,1,161,1,125,3,103,0,125,4,124,3,100,0, - 107,9,114,60,116,3,160,4,124,1,124,3,161,2,83,0, - 116,3,160,5,124,1,100,0,161,2,125,5,124,4,124,5, - 95,6,124,5,83,0,41,2,78,114,121,0,0,0,41,7, - 114,112,0,0,0,114,121,0,0,0,114,179,0,0,0,114, - 118,0,0,0,114,176,0,0,0,114,158,0,0,0,114,154, - 0,0,0,41,6,114,168,0,0,0,114,123,0,0,0,114, - 251,0,0,0,114,124,0,0,0,114,125,0,0,0,114,162, + 0,218,8,95,95,105,116,101,114,95,95,58,4,0,0,115, + 2,0,0,0,0,1,122,23,95,78,97,109,101,115,112,97, + 99,101,80,97,116,104,46,95,95,105,116,101,114,95,95,99, + 3,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, + 67,0,0,0,115,14,0,0,0,124,2,124,0,106,0,124, + 1,60,0,100,0,83,0,41,1,78,41,1,114,236,0,0, + 0,41,3,114,104,0,0,0,218,5,105,110,100,101,120,114, + 37,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,218,11,95,95,115,101,116,105,116,101,109,95,95, + 61,4,0,0,115,2,0,0,0,0,1,122,26,95,78,97, + 109,101,115,112,97,99,101,80,97,116,104,46,95,95,115,101, + 116,105,116,101,109,95,95,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,12,0,0, + 0,116,0,124,0,160,1,161,0,131,1,83,0,41,1,78, + 41,2,114,33,0,0,0,114,244,0,0,0,41,1,114,104, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,218,16,95,108,101,103,97,99,121,95,103,101,116,95, - 115,112,101,99,80,4,0,0,115,18,0,0,0,0,4,10, - 1,16,2,10,1,4,1,8,1,12,1,12,1,6,1,122, - 27,80,97,116,104,70,105,110,100,101,114,46,95,108,101,103, - 97,99,121,95,103,101,116,95,115,112,101,99,78,99,4,0, - 0,0,0,0,0,0,9,0,0,0,5,0,0,0,67,0, - 0,0,115,170,0,0,0,103,0,125,4,120,160,124,2,68, - 0,93,130,125,5,116,0,124,5,116,1,116,2,102,2,131, - 2,115,30,113,10,124,0,160,3,124,5,161,1,125,6,124, - 6,100,1,107,9,114,10,116,4,124,6,100,2,131,2,114, - 72,124,6,160,5,124,1,124,3,161,2,125,7,110,12,124, - 0,160,6,124,1,124,6,161,2,125,7,124,7,100,1,107, - 8,114,94,113,10,124,7,106,7,100,1,107,9,114,108,124, - 7,83,0,124,7,106,8,125,8,124,8,100,1,107,8,114, - 130,116,9,100,3,131,1,130,1,124,4,160,10,124,8,161, - 1,1,0,113,10,87,0,116,11,160,12,124,1,100,1,161, - 2,125,7,124,4,124,7,95,8,124,7,83,0,100,1,83, - 0,41,4,122,63,70,105,110,100,32,116,104,101,32,108,111, - 97,100,101,114,32,111,114,32,110,97,109,101,115,112,97,99, - 101,95,112,97,116,104,32,102,111,114,32,116,104,105,115,32, - 109,111,100,117,108,101,47,112,97,99,107,97,103,101,32,110, - 97,109,101,46,78,114,178,0,0,0,122,19,115,112,101,99, - 32,109,105,115,115,105,110,103,32,108,111,97,100,101,114,41, - 13,114,141,0,0,0,114,73,0,0,0,218,5,98,121,116, - 101,115,114,255,0,0,0,114,112,0,0,0,114,178,0,0, - 0,114,0,1,0,0,114,124,0,0,0,114,154,0,0,0, - 114,103,0,0,0,114,147,0,0,0,114,118,0,0,0,114, - 158,0,0,0,41,9,114,168,0,0,0,114,123,0,0,0, - 114,37,0,0,0,114,177,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,251,0,0,0,114,162,0,0,0,114,125,0,0,0, + 0,0,218,7,95,95,108,101,110,95,95,64,4,0,0,115, + 2,0,0,0,0,1,122,22,95,78,97,109,101,115,112,97, + 99,101,80,97,116,104,46,95,95,108,101,110,95,95,99,1, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,12,0,0,0,100,1,160,0,124,0,106,1, + 161,1,83,0,41,2,78,122,20,95,78,97,109,101,115,112, + 97,99,101,80,97,116,104,40,123,33,114,125,41,41,2,114, + 50,0,0,0,114,236,0,0,0,41,1,114,104,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218, - 9,95,103,101,116,95,115,112,101,99,95,4,0,0,115,40, - 0,0,0,0,5,4,1,10,1,14,1,2,1,10,1,8, - 1,10,1,14,2,12,1,8,1,2,1,10,1,4,1,6, - 1,8,1,8,5,14,2,12,1,6,1,122,20,80,97,116, - 104,70,105,110,100,101,114,46,95,103,101,116,95,115,112,101, - 99,99,4,0,0,0,0,0,0,0,6,0,0,0,5,0, - 0,0,67,0,0,0,115,100,0,0,0,124,2,100,1,107, - 8,114,14,116,0,106,1,125,2,124,0,160,2,124,1,124, - 2,124,3,161,3,125,4,124,4,100,1,107,8,114,40,100, - 1,83,0,124,4,106,3,100,1,107,8,114,92,124,4,106, - 4,125,5,124,5,114,86,100,2,124,4,95,5,116,6,124, - 1,124,5,124,0,106,2,131,3,124,4,95,4,124,4,83, - 0,100,1,83,0,110,4,124,4,83,0,100,1,83,0,41, - 3,122,141,84,114,121,32,116,111,32,102,105,110,100,32,97, - 32,115,112,101,99,32,102,111,114,32,39,102,117,108,108,110, - 97,109,101,39,32,111,110,32,115,121,115,46,112,97,116,104, - 32,111,114,32,39,112,97,116,104,39,46,10,10,32,32,32, - 32,32,32,32,32,84,104,101,32,115,101,97,114,99,104,32, - 105,115,32,98,97,115,101,100,32,111,110,32,115,121,115,46, - 112,97,116,104,95,104,111,111,107,115,32,97,110,100,32,115, - 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, - 95,99,97,99,104,101,46,10,32,32,32,32,32,32,32,32, - 78,90,9,110,97,109,101,115,112,97,99,101,41,7,114,8, - 0,0,0,114,37,0,0,0,114,3,1,0,0,114,124,0, - 0,0,114,154,0,0,0,114,156,0,0,0,114,226,0,0, - 0,41,6,114,168,0,0,0,114,123,0,0,0,114,37,0, - 0,0,114,177,0,0,0,114,162,0,0,0,114,2,1,0, - 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 114,178,0,0,0,127,4,0,0,115,26,0,0,0,0,6, - 8,1,6,1,14,1,8,1,4,1,10,1,6,1,4,3, - 6,1,16,1,4,2,6,2,122,20,80,97,116,104,70,105, - 110,100,101,114,46,102,105,110,100,95,115,112,101,99,99,3, - 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, - 0,0,0,115,30,0,0,0,124,0,160,0,124,1,124,2, - 161,2,125,3,124,3,100,1,107,8,114,24,100,1,83,0, - 124,3,106,1,83,0,41,2,122,170,102,105,110,100,32,116, - 104,101,32,109,111,100,117,108,101,32,111,110,32,115,121,115, - 46,112,97,116,104,32,111,114,32,39,112,97,116,104,39,32, - 98,97,115,101,100,32,111,110,32,115,121,115,46,112,97,116, - 104,95,104,111,111,107,115,32,97,110,100,10,32,32,32,32, - 32,32,32,32,115,121,115,46,112,97,116,104,95,105,109,112, - 111,114,116,101,114,95,99,97,99,104,101,46,10,10,32,32, - 32,32,32,32,32,32,84,104,105,115,32,109,101,116,104,111, - 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 32,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, - 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 32,32,32,32,78,41,2,114,178,0,0,0,114,124,0,0, - 0,41,4,114,168,0,0,0,114,123,0,0,0,114,37,0, - 0,0,114,162,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,179,0,0,0,151,4,0,0,115, - 8,0,0,0,0,8,12,1,8,1,4,1,122,22,80,97, - 116,104,70,105,110,100,101,114,46,102,105,110,100,95,109,111, - 100,117,108,101,41,1,78,41,2,78,78,41,1,78,41,12, - 114,109,0,0,0,114,108,0,0,0,114,110,0,0,0,114, - 111,0,0,0,114,180,0,0,0,114,248,0,0,0,114,253, - 0,0,0,114,255,0,0,0,114,0,1,0,0,114,3,1, - 0,0,114,178,0,0,0,114,179,0,0,0,114,4,0,0, + 8,95,95,114,101,112,114,95,95,67,4,0,0,115,2,0, + 0,0,0,1,122,23,95,78,97,109,101,115,112,97,99,101, + 80,97,116,104,46,95,95,114,101,112,114,95,95,99,2,0, + 0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,0, + 0,0,115,12,0,0,0,124,1,124,0,160,0,161,0,107, + 6,83,0,41,1,78,41,1,114,244,0,0,0,41,2,114, + 104,0,0,0,218,4,105,116,101,109,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,218,12,95,95,99,111,110, + 116,97,105,110,115,95,95,70,4,0,0,115,2,0,0,0, + 0,1,122,27,95,78,97,109,101,115,112,97,99,101,80,97, + 116,104,46,95,95,99,111,110,116,97,105,110,115,95,95,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 67,0,0,0,115,16,0,0,0,124,0,106,0,160,1,124, + 1,161,1,1,0,100,0,83,0,41,1,78,41,2,114,236, + 0,0,0,114,167,0,0,0,41,2,114,104,0,0,0,114, + 251,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,114,167,0,0,0,73,4,0,0,115,2,0,0, + 0,0,1,122,21,95,78,97,109,101,115,112,97,99,101,80, + 97,116,104,46,97,112,112,101,110,100,78,41,14,114,109,0, + 0,0,114,108,0,0,0,114,110,0,0,0,114,111,0,0, + 0,114,188,0,0,0,114,242,0,0,0,114,237,0,0,0, + 114,244,0,0,0,114,246,0,0,0,114,248,0,0,0,114, + 249,0,0,0,114,250,0,0,0,114,252,0,0,0,114,167, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,114,234,0,0,0,18,4,0,0, + 115,20,0,0,0,12,7,8,6,8,10,8,4,8,13,8, + 3,8,3,8,3,8,3,8,3,114,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,80,0,0,0,101,0,90,1,100,0,90,2, + 100,1,100,2,132,0,90,3,101,4,100,3,100,4,132,0, + 131,1,90,5,100,5,100,6,132,0,90,6,100,7,100,8, + 132,0,90,7,100,9,100,10,132,0,90,8,100,11,100,12, + 132,0,90,9,100,13,100,14,132,0,90,10,100,15,100,16, + 132,0,90,11,100,17,83,0,41,18,218,16,95,78,97,109, + 101,115,112,97,99,101,76,111,97,100,101,114,99,4,0,0, + 0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0, + 0,115,18,0,0,0,116,0,124,1,124,2,124,3,131,3, + 124,0,95,1,100,0,83,0,41,1,78,41,2,114,234,0, + 0,0,114,236,0,0,0,41,4,114,104,0,0,0,114,102, + 0,0,0,114,37,0,0,0,114,240,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,6,0,0,0,114,188,0,0, + 0,79,4,0,0,115,2,0,0,0,0,1,122,25,95,78, + 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,95, + 95,105,110,105,116,95,95,99,2,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,67,0,0,0,115,12,0,0, + 0,100,1,160,0,124,1,106,1,161,1,83,0,41,2,122, + 115,82,101,116,117,114,110,32,114,101,112,114,32,102,111,114, + 32,116,104,101,32,109,111,100,117,108,101,46,10,10,32,32, + 32,32,32,32,32,32,84,104,101,32,109,101,116,104,111,100, + 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, + 32,84,104,101,32,105,109,112,111,114,116,32,109,97,99,104, + 105,110,101,114,121,32,100,111,101,115,32,116,104,101,32,106, + 111,98,32,105,116,115,101,108,102,46,10,10,32,32,32,32, + 32,32,32,32,122,25,60,109,111,100,117,108,101,32,123,33, + 114,125,32,40,110,97,109,101,115,112,97,99,101,41,62,41, + 2,114,50,0,0,0,114,109,0,0,0,41,2,114,174,0, + 0,0,114,193,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,218,11,109,111,100,117,108,101,95,114, + 101,112,114,82,4,0,0,115,2,0,0,0,0,7,122,28, + 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, + 46,109,111,100,117,108,101,95,114,101,112,114,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,83,0,41,2,78,84,114,4, + 0,0,0,41,2,114,104,0,0,0,114,123,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,163, + 0,0,0,91,4,0,0,115,2,0,0,0,0,1,122,27, + 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, + 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,78,114,32,0,0, + 0,114,4,0,0,0,41,2,114,104,0,0,0,114,123,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,114,204,0,0,0,94,4,0,0,115,2,0,0,0,0, + 1,122,27,95,78,97,109,101,115,112,97,99,101,76,111,97, + 100,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, + 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, + 0,0,0,115,16,0,0,0,116,0,100,1,100,2,100,3, + 100,4,100,5,141,4,83,0,41,6,78,114,32,0,0,0, + 122,8,60,115,116,114,105,110,103,62,114,192,0,0,0,84, + 41,1,114,206,0,0,0,41,1,114,207,0,0,0,41,2, + 114,104,0,0,0,114,123,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,114,190,0,0,0,97,4, + 0,0,115,2,0,0,0,0,1,122,25,95,78,97,109,101, + 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, + 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, + 83,0,41,2,122,42,85,115,101,32,100,101,102,97,117,108, + 116,32,115,101,109,97,110,116,105,99,115,32,102,111,114,32, + 109,111,100,117,108,101,32,99,114,101,97,116,105,111,110,46, + 78,114,4,0,0,0,41,2,114,104,0,0,0,114,168,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,114,189,0,0,0,100,4,0,0,115,0,0,0,0,122, + 30,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, + 114,46,99,114,101,97,116,101,95,109,111,100,117,108,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, + 67,0,0,0,115,4,0,0,0,100,0,83,0,41,1,78, + 114,4,0,0,0,41,2,114,104,0,0,0,114,193,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 114,247,0,0,0,33,4,0,0,115,20,0,0,0,12,4, - 12,8,12,13,12,22,12,15,2,1,12,31,2,1,12,23, - 2,1,114,247,0,0,0,99,0,0,0,0,0,0,0,0, - 0,0,0,0,3,0,0,0,64,0,0,0,115,90,0,0, - 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, - 3,132,0,90,4,100,4,100,5,132,0,90,5,101,6,90, - 7,100,6,100,7,132,0,90,8,100,8,100,9,132,0,90, - 9,100,19,100,11,100,12,132,1,90,10,100,13,100,14,132, - 0,90,11,101,12,100,15,100,16,132,0,131,1,90,13,100, - 17,100,18,132,0,90,14,100,10,83,0,41,20,218,10,70, - 105,108,101,70,105,110,100,101,114,122,172,70,105,108,101,45, - 98,97,115,101,100,32,102,105,110,100,101,114,46,10,10,32, - 32,32,32,73,110,116,101,114,97,99,116,105,111,110,115,32, - 119,105,116,104,32,116,104,101,32,102,105,108,101,32,115,121, - 115,116,101,109,32,97,114,101,32,99,97,99,104,101,100,32, - 102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,44, - 32,98,101,105,110,103,10,32,32,32,32,114,101,102,114,101, - 115,104,101,100,32,119,104,101,110,32,116,104,101,32,100,105, - 114,101,99,116,111,114,121,32,116,104,101,32,102,105,110,100, - 101,114,32,105,115,32,104,97,110,100,108,105,110,103,32,104, - 97,115,32,98,101,101,110,32,109,111,100,105,102,105,101,100, - 46,10,10,32,32,32,32,99,2,0,0,0,0,0,0,0, - 5,0,0,0,6,0,0,0,7,0,0,0,115,88,0,0, - 0,103,0,125,3,120,40,124,2,68,0,93,32,92,2,137, - 0,125,4,124,3,160,0,135,0,102,1,100,1,100,2,132, - 8,124,4,68,0,131,1,161,1,1,0,113,10,87,0,124, - 3,124,0,95,1,124,1,112,58,100,3,124,0,95,2,100, - 6,124,0,95,3,116,4,131,0,124,0,95,5,116,4,131, - 0,124,0,95,6,100,5,83,0,41,7,122,154,73,110,105, - 116,105,97,108,105,122,101,32,119,105,116,104,32,116,104,101, - 32,112,97,116,104,32,116,111,32,115,101,97,114,99,104,32, - 111,110,32,97,110,100,32,97,32,118,97,114,105,97,98,108, - 101,32,110,117,109,98,101,114,32,111,102,10,32,32,32,32, - 32,32,32,32,50,45,116,117,112,108,101,115,32,99,111,110, - 116,97,105,110,105,110,103,32,116,104,101,32,108,111,97,100, - 101,114,32,97,110,100,32,116,104,101,32,102,105,108,101,32, - 115,117,102,102,105,120,101,115,32,116,104,101,32,108,111,97, - 100,101,114,10,32,32,32,32,32,32,32,32,114,101,99,111, - 103,110,105,122,101,115,46,99,1,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,51,0,0,0,115,22,0,0, - 0,124,0,93,14,125,1,124,1,136,0,102,2,86,0,1, - 0,113,2,100,0,83,0,41,1,78,114,4,0,0,0,41, - 2,114,24,0,0,0,114,221,0,0,0,41,1,114,124,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,223,0,0, - 0,180,4,0,0,115,2,0,0,0,4,0,122,38,70,105, - 108,101,70,105,110,100,101,114,46,95,95,105,110,105,116,95, - 95,46,60,108,111,99,97,108,115,62,46,60,103,101,110,101, - 120,112,114,62,114,61,0,0,0,114,31,0,0,0,78,114, - 91,0,0,0,41,7,114,147,0,0,0,218,8,95,108,111, - 97,100,101,114,115,114,37,0,0,0,218,11,95,112,97,116, - 104,95,109,116,105,109,101,218,3,115,101,116,218,11,95,112, - 97,116,104,95,99,97,99,104,101,218,19,95,114,101,108,97, - 120,101,100,95,112,97,116,104,95,99,97,99,104,101,41,5, - 114,104,0,0,0,114,37,0,0,0,218,14,108,111,97,100, - 101,114,95,100,101,116,97,105,108,115,90,7,108,111,97,100, - 101,114,115,114,164,0,0,0,114,4,0,0,0,41,1,114, - 124,0,0,0,114,6,0,0,0,114,182,0,0,0,174,4, - 0,0,115,16,0,0,0,0,4,4,1,14,1,28,1,6, - 2,10,1,6,1,8,1,122,19,70,105,108,101,70,105,110, - 100,101,114,46,95,95,105,110,105,116,95,95,99,1,0,0, - 0,0,0,0,0,1,0,0,0,2,0,0,0,67,0,0, - 0,115,10,0,0,0,100,3,124,0,95,0,100,2,83,0, - 41,4,122,31,73,110,118,97,108,105,100,97,116,101,32,116, - 104,101,32,100,105,114,101,99,116,111,114,121,32,109,116,105, - 109,101,46,114,31,0,0,0,78,114,91,0,0,0,41,1, - 114,6,1,0,0,41,1,114,104,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,114,248,0,0,0, - 188,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,3,0,0,0,67,0,0,0,115,42, - 0,0,0,124,0,160,0,124,1,161,1,125,2,124,2,100, - 1,107,8,114,26,100,1,103,0,102,2,83,0,124,2,106, - 1,124,2,106,2,112,38,103,0,102,2,83,0,41,2,122, - 197,84,114,121,32,116,111,32,102,105,110,100,32,97,32,108, - 111,97,100,101,114,32,102,111,114,32,116,104,101,32,115,112, - 101,99,105,102,105,101,100,32,109,111,100,117,108,101,44,32, - 111,114,32,116,104,101,32,110,97,109,101,115,112,97,99,101, - 10,32,32,32,32,32,32,32,32,112,97,99,107,97,103,101, - 32,112,111,114,116,105,111,110,115,46,32,82,101,116,117,114, - 110,115,32,40,108,111,97,100,101,114,44,32,108,105,115,116, - 45,111,102,45,112,111,114,116,105,111,110,115,41,46,10,10, + 114,194,0,0,0,103,4,0,0,115,2,0,0,0,0,1, + 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, + 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, + 0,0,0,115,26,0,0,0,116,0,160,1,100,1,124,0, + 106,2,161,2,1,0,116,0,160,3,124,0,124,1,161,2, + 83,0,41,2,122,98,76,111,97,100,32,97,32,110,97,109, + 101,115,112,97,99,101,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, + 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,32,32,32,32,122,38,110,97,109,101,115,112, + 97,99,101,32,109,111,100,117,108,101,32,108,111,97,100,101, + 100,32,119,105,116,104,32,112,97,116,104,32,123,33,114,125, + 41,4,114,118,0,0,0,114,132,0,0,0,114,236,0,0, + 0,114,195,0,0,0,41,2,114,104,0,0,0,114,123,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,114,196,0,0,0,106,4,0,0,115,6,0,0,0,0, + 7,6,1,8,1,122,28,95,78,97,109,101,115,112,97,99, + 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, + 117,108,101,78,41,12,114,109,0,0,0,114,108,0,0,0, + 114,110,0,0,0,114,188,0,0,0,114,186,0,0,0,114, + 254,0,0,0,114,163,0,0,0,114,204,0,0,0,114,190, + 0,0,0,114,189,0,0,0,114,194,0,0,0,114,196,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,114,253,0,0,0,78,4,0,0,115, + 16,0,0,0,8,1,8,3,12,9,8,3,8,3,8,3, + 8,3,8,3,114,253,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,90,1,100,0,90,2,100,1,90,3,101, + 4,100,2,100,3,132,0,131,1,90,5,101,4,100,4,100, + 5,132,0,131,1,90,6,101,4,100,6,100,7,132,0,131, + 1,90,7,101,4,100,8,100,9,132,0,131,1,90,8,101, + 4,100,17,100,11,100,12,132,1,131,1,90,9,101,4,100, + 18,100,13,100,14,132,1,131,1,90,10,101,4,100,19,100, + 15,100,16,132,1,131,1,90,11,100,10,83,0,41,20,218, + 10,80,97,116,104,70,105,110,100,101,114,122,62,77,101,116, + 97,32,112,97,116,104,32,102,105,110,100,101,114,32,102,111, + 114,32,115,121,115,46,112,97,116,104,32,97,110,100,32,112, + 97,99,107,97,103,101,32,95,95,112,97,116,104,95,95,32, + 97,116,116,114,105,98,117,116,101,115,46,99,1,0,0,0, + 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, + 115,42,0,0,0,120,36,116,0,106,1,160,2,161,0,68, + 0,93,22,125,1,116,3,124,1,100,1,131,2,114,12,124, + 1,160,4,161,0,1,0,113,12,87,0,100,2,83,0,41, + 3,122,125,67,97,108,108,32,116,104,101,32,105,110,118,97, + 108,105,100,97,116,101,95,99,97,99,104,101,115,40,41,32, + 109,101,116,104,111,100,32,111,110,32,97,108,108,32,112,97, + 116,104,32,101,110,116,114,121,32,102,105,110,100,101,114,115, + 10,32,32,32,32,32,32,32,32,115,116,111,114,101,100,32, + 105,110,32,115,121,115,46,112,97,116,104,95,105,109,112,111, + 114,116,101,114,95,99,97,99,104,101,115,32,40,119,104,101, + 114,101,32,105,109,112,108,101,109,101,110,116,101,100,41,46, + 218,17,105,110,118,97,108,105,100,97,116,101,95,99,97,99, + 104,101,115,78,41,5,114,8,0,0,0,218,19,112,97,116, + 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, + 218,6,118,97,108,117,101,115,114,112,0,0,0,114,0,1, + 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,6,0,0,0, + 114,0,1,0,0,124,4,0,0,115,6,0,0,0,0,4, + 16,1,10,1,122,28,80,97,116,104,70,105,110,100,101,114, + 46,105,110,118,97,108,105,100,97,116,101,95,99,97,99,104, + 101,115,99,2,0,0,0,0,0,0,0,3,0,0,0,12, + 0,0,0,67,0,0,0,115,84,0,0,0,116,0,106,1, + 100,1,107,9,114,28,116,0,106,1,115,28,116,2,160,3, + 100,2,116,4,161,2,1,0,120,50,116,0,106,1,68,0, + 93,36,125,2,121,8,124,2,124,1,131,1,83,0,4,0, + 116,5,107,10,114,70,1,0,1,0,1,0,119,36,89,0, + 113,36,88,0,113,36,87,0,100,1,83,0,100,1,83,0, + 41,3,122,46,83,101,97,114,99,104,32,115,121,115,46,112, + 97,116,104,95,104,111,111,107,115,32,102,111,114,32,97,32, + 102,105,110,100,101,114,32,102,111,114,32,39,112,97,116,104, + 39,46,78,122,23,115,121,115,46,112,97,116,104,95,104,111, + 111,107,115,32,105,115,32,101,109,112,116,121,41,6,114,8, + 0,0,0,218,10,112,97,116,104,95,104,111,111,107,115,114, + 63,0,0,0,114,64,0,0,0,114,122,0,0,0,114,103, + 0,0,0,41,3,114,174,0,0,0,114,37,0,0,0,90, + 4,104,111,111,107,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,218,11,95,112,97,116,104,95,104,111,111,107, + 115,132,4,0,0,115,16,0,0,0,0,3,16,1,12,1, + 12,1,2,1,8,1,14,1,12,2,122,22,80,97,116,104, + 70,105,110,100,101,114,46,95,112,97,116,104,95,104,111,111, + 107,115,99,2,0,0,0,0,0,0,0,3,0,0,0,19, + 0,0,0,67,0,0,0,115,102,0,0,0,124,1,100,1, + 107,2,114,42,121,12,116,0,160,1,161,0,125,1,87,0, + 110,20,4,0,116,2,107,10,114,40,1,0,1,0,1,0, + 100,2,83,0,88,0,121,14,116,3,106,4,124,1,25,0, + 125,2,87,0,110,40,4,0,116,5,107,10,114,96,1,0, + 1,0,1,0,124,0,160,6,124,1,161,1,125,2,124,2, + 116,3,106,4,124,1,60,0,89,0,110,2,88,0,124,2, + 83,0,41,3,122,210,71,101,116,32,116,104,101,32,102,105, + 110,100,101,114,32,102,111,114,32,116,104,101,32,112,97,116, + 104,32,101,110,116,114,121,32,102,114,111,109,32,115,121,115, + 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, + 97,99,104,101,46,10,10,32,32,32,32,32,32,32,32,73, + 102,32,116,104,101,32,112,97,116,104,32,101,110,116,114,121, + 32,105,115,32,110,111,116,32,105,110,32,116,104,101,32,99, + 97,99,104,101,44,32,102,105,110,100,32,116,104,101,32,97, + 112,112,114,111,112,114,105,97,116,101,32,102,105,110,100,101, + 114,10,32,32,32,32,32,32,32,32,97,110,100,32,99,97, + 99,104,101,32,105,116,46,32,73,102,32,110,111,32,102,105, + 110,100,101,114,32,105,115,32,97,118,97,105,108,97,98,108, + 101,44,32,115,116,111,114,101,32,78,111,110,101,46,10,10, + 32,32,32,32,32,32,32,32,114,32,0,0,0,78,41,7, + 114,3,0,0,0,114,47,0,0,0,218,17,70,105,108,101, + 78,111,116,70,111,117,110,100,69,114,114,111,114,114,8,0, + 0,0,114,1,1,0,0,218,8,75,101,121,69,114,114,111, + 114,114,5,1,0,0,41,3,114,174,0,0,0,114,37,0, + 0,0,114,3,1,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,218,20,95,112,97,116,104,95,105,109, + 112,111,114,116,101,114,95,99,97,99,104,101,145,4,0,0, + 115,22,0,0,0,0,8,8,1,2,1,12,1,14,3,6, + 1,2,1,14,1,14,1,10,1,16,1,122,31,80,97,116, + 104,70,105,110,100,101,114,46,95,112,97,116,104,95,105,109, + 112,111,114,116,101,114,95,99,97,99,104,101,99,3,0,0, + 0,0,0,0,0,6,0,0,0,4,0,0,0,67,0,0, + 0,115,82,0,0,0,116,0,124,2,100,1,131,2,114,26, + 124,2,160,1,124,1,161,1,92,2,125,3,125,4,110,14, + 124,2,160,2,124,1,161,1,125,3,103,0,125,4,124,3, + 100,0,107,9,114,60,116,3,160,4,124,1,124,3,161,2, + 83,0,116,3,160,5,124,1,100,0,161,2,125,5,124,4, + 124,5,95,6,124,5,83,0,41,2,78,114,121,0,0,0, + 41,7,114,112,0,0,0,114,121,0,0,0,114,185,0,0, + 0,114,118,0,0,0,114,182,0,0,0,114,164,0,0,0, + 114,160,0,0,0,41,6,114,174,0,0,0,114,123,0,0, + 0,114,3,1,0,0,114,124,0,0,0,114,125,0,0,0, + 114,168,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,218,16,95,108,101,103,97,99,121,95,103,101, + 116,95,115,112,101,99,167,4,0,0,115,18,0,0,0,0, + 4,10,1,16,2,10,1,4,1,8,1,12,1,12,1,6, + 1,122,27,80,97,116,104,70,105,110,100,101,114,46,95,108, + 101,103,97,99,121,95,103,101,116,95,115,112,101,99,78,99, + 4,0,0,0,0,0,0,0,9,0,0,0,5,0,0,0, + 67,0,0,0,115,170,0,0,0,103,0,125,4,120,160,124, + 2,68,0,93,130,125,5,116,0,124,5,116,1,116,2,102, + 2,131,2,115,30,113,10,124,0,160,3,124,5,161,1,125, + 6,124,6,100,1,107,9,114,10,116,4,124,6,100,2,131, + 2,114,72,124,6,160,5,124,1,124,3,161,2,125,7,110, + 12,124,0,160,6,124,1,124,6,161,2,125,7,124,7,100, + 1,107,8,114,94,113,10,124,7,106,7,100,1,107,9,114, + 108,124,7,83,0,124,7,106,8,125,8,124,8,100,1,107, + 8,114,130,116,9,100,3,131,1,130,1,124,4,160,10,124, + 8,161,1,1,0,113,10,87,0,116,11,160,12,124,1,100, + 1,161,2,125,7,124,4,124,7,95,8,124,7,83,0,100, + 1,83,0,41,4,122,63,70,105,110,100,32,116,104,101,32, + 108,111,97,100,101,114,32,111,114,32,110,97,109,101,115,112, + 97,99,101,95,112,97,116,104,32,102,111,114,32,116,104,105, + 115,32,109,111,100,117,108,101,47,112,97,99,107,97,103,101, + 32,110,97,109,101,46,78,114,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,143,0,0,0,114,73,0,0,0,218,5,98, + 121,116,101,115,114,8,1,0,0,114,112,0,0,0,114,184, + 0,0,0,114,9,1,0,0,114,124,0,0,0,114,160,0, + 0,0,114,103,0,0,0,114,149,0,0,0,114,118,0,0, + 0,114,164,0,0,0,41,9,114,174,0,0,0,114,123,0, + 0,0,114,37,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,3,1,0,0,114,168,0,0,0,114,125,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,218,9,95,103,101,116,95,115,112,101,99,182,4,0,0, + 115,40,0,0,0,0,5,4,1,10,1,14,1,2,1,10, + 1,8,1,10,1,14,2,12,1,8,1,2,1,10,1,4, + 1,6,1,8,1,8,5,14,2,12,1,6,1,122,20,80, + 97,116,104,70,105,110,100,101,114,46,95,103,101,116,95,115, + 112,101,99,99,4,0,0,0,0,0,0,0,6,0,0,0, + 5,0,0,0,67,0,0,0,115,100,0,0,0,124,2,100, + 1,107,8,114,14,116,0,106,1,125,2,124,0,160,2,124, + 1,124,2,124,3,161,3,125,4,124,4,100,1,107,8,114, + 40,100,1,83,0,124,4,106,3,100,1,107,8,114,92,124, + 4,106,4,125,5,124,5,114,86,100,2,124,4,95,5,116, + 6,124,1,124,5,124,0,106,2,131,3,124,4,95,4,124, + 4,83,0,100,1,83,0,110,4,124,4,83,0,100,1,83, + 0,41,3,122,141,84,114,121,32,116,111,32,102,105,110,100, + 32,97,32,115,112,101,99,32,102,111,114,32,39,102,117,108, + 108,110,97,109,101,39,32,111,110,32,115,121,115,46,112,97, + 116,104,32,111,114,32,39,112,97,116,104,39,46,10,10,32, + 32,32,32,32,32,32,32,84,104,101,32,115,101,97,114,99, + 104,32,105,115,32,98,97,115,101,100,32,111,110,32,115,121, + 115,46,112,97,116,104,95,104,111,111,107,115,32,97,110,100, + 32,115,121,115,46,112,97,116,104,95,105,109,112,111,114,116, + 101,114,95,99,97,99,104,101,46,10,32,32,32,32,32,32, + 32,32,78,90,9,110,97,109,101,115,112,97,99,101,41,7, + 114,8,0,0,0,114,37,0,0,0,114,12,1,0,0,114, + 124,0,0,0,114,160,0,0,0,114,162,0,0,0,114,234, + 0,0,0,41,6,114,174,0,0,0,114,123,0,0,0,114, + 37,0,0,0,114,183,0,0,0,114,168,0,0,0,114,11, + 1,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, + 0,0,114,184,0,0,0,214,4,0,0,115,26,0,0,0, + 0,6,8,1,6,1,14,1,8,1,4,1,10,1,6,1, + 4,3,6,1,16,1,4,2,6,2,122,20,80,97,116,104, + 70,105,110,100,101,114,46,102,105,110,100,95,115,112,101,99, + 99,3,0,0,0,0,0,0,0,4,0,0,0,4,0,0, + 0,67,0,0,0,115,30,0,0,0,124,0,160,0,124,1, + 124,2,161,2,125,3,124,3,100,1,107,8,114,24,100,1, + 83,0,124,3,106,1,83,0,41,2,122,170,102,105,110,100, + 32,116,104,101,32,109,111,100,117,108,101,32,111,110,32,115, + 121,115,46,112,97,116,104,32,111,114,32,39,112,97,116,104, + 39,32,98,97,115,101,100,32,111,110,32,115,121,115,46,112, + 97,116,104,95,104,111,111,107,115,32,97,110,100,10,32,32, + 32,32,32,32,32,32,115,121,115,46,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,46,10,10, 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, - 32,32,32,32,32,32,78,41,3,114,178,0,0,0,114,124, - 0,0,0,114,154,0,0,0,41,3,114,104,0,0,0,114, - 123,0,0,0,114,162,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,114,121,0,0,0,194,4,0, - 0,115,8,0,0,0,0,7,10,1,8,1,8,1,122,22, - 70,105,108,101,70,105,110,100,101,114,46,102,105,110,100,95, - 108,111,97,100,101,114,99,6,0,0,0,0,0,0,0,7, - 0,0,0,6,0,0,0,67,0,0,0,115,26,0,0,0, - 124,1,124,2,124,3,131,2,125,6,116,0,124,2,124,3, - 124,6,124,4,100,1,141,4,83,0,41,2,78,41,2,114, - 124,0,0,0,114,154,0,0,0,41,1,114,165,0,0,0, - 41,7,114,104,0,0,0,114,163,0,0,0,114,123,0,0, - 0,114,37,0,0,0,90,4,115,109,115,108,114,177,0,0, - 0,114,124,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,114,3,1,0,0,206,4,0,0,115,6, - 0,0,0,0,1,10,1,8,1,122,20,70,105,108,101,70, - 105,110,100,101,114,46,95,103,101,116,95,115,112,101,99,78, - 99,3,0,0,0,0,0,0,0,14,0,0,0,16,0,0, - 0,67,0,0,0,115,98,1,0,0,100,1,125,3,124,1, - 160,0,100,2,161,1,100,3,25,0,125,4,121,24,116,1, - 124,0,106,2,112,34,116,3,160,4,161,0,131,1,106,5, - 125,5,87,0,110,24,4,0,116,6,107,10,114,66,1,0, - 1,0,1,0,100,10,125,5,89,0,110,2,88,0,124,5, - 124,0,106,7,107,3,114,92,124,0,160,8,161,0,1,0, - 124,5,124,0,95,7,116,9,131,0,114,114,124,0,106,10, - 125,6,124,4,160,11,161,0,125,7,110,10,124,0,106,12, - 125,6,124,4,125,7,124,7,124,6,107,6,114,218,116,13, - 124,0,106,2,124,4,131,2,125,8,120,72,124,0,106,14, - 68,0,93,54,92,2,125,9,125,10,100,5,124,9,23,0, - 125,11,116,13,124,8,124,11,131,2,125,12,116,15,124,12, - 131,1,114,152,124,0,160,16,124,10,124,1,124,12,124,8, - 103,1,124,2,161,5,83,0,113,152,87,0,116,17,124,8, - 131,1,125,3,120,88,124,0,106,14,68,0,93,78,92,2, - 125,9,125,10,116,13,124,0,106,2,124,4,124,9,23,0, - 131,2,125,12,116,18,106,19,100,6,124,12,100,3,100,7, - 141,3,1,0,124,7,124,9,23,0,124,6,107,6,114,226, - 116,15,124,12,131,1,114,226,124,0,160,16,124,10,124,1, - 124,12,100,8,124,2,161,5,83,0,113,226,87,0,124,3, - 144,1,114,94,116,18,160,19,100,9,124,8,161,2,1,0, - 116,18,160,20,124,1,100,8,161,2,125,13,124,8,103,1, - 124,13,95,21,124,13,83,0,100,8,83,0,41,11,122,111, - 84,114,121,32,116,111,32,102,105,110,100,32,97,32,115,112, - 101,99,32,102,111,114,32,116,104,101,32,115,112,101,99,105, - 102,105,101,100,32,109,111,100,117,108,101,46,10,10,32,32, - 32,32,32,32,32,32,82,101,116,117,114,110,115,32,116,104, - 101,32,109,97,116,99,104,105,110,103,32,115,112,101,99,44, - 32,111,114,32,78,111,110,101,32,105,102,32,110,111,116,32, - 102,111,117,110,100,46,10,32,32,32,32,32,32,32,32,70, - 114,61,0,0,0,114,59,0,0,0,114,31,0,0,0,114, - 182,0,0,0,122,9,116,114,121,105,110,103,32,123,125,41, - 1,90,9,118,101,114,98,111,115,105,116,121,78,122,25,112, - 111,115,115,105,98,108,101,32,110,97,109,101,115,112,97,99, - 101,32,102,111,114,32,123,125,114,91,0,0,0,41,22,114, - 34,0,0,0,114,41,0,0,0,114,37,0,0,0,114,3, - 0,0,0,114,47,0,0,0,114,215,0,0,0,114,42,0, - 0,0,114,6,1,0,0,218,11,95,102,105,108,108,95,99, - 97,99,104,101,114,7,0,0,0,114,9,1,0,0,114,92, - 0,0,0,114,8,1,0,0,114,30,0,0,0,114,5,1, - 0,0,114,46,0,0,0,114,3,1,0,0,114,48,0,0, - 0,114,118,0,0,0,114,133,0,0,0,114,158,0,0,0, - 114,154,0,0,0,41,14,114,104,0,0,0,114,123,0,0, - 0,114,177,0,0,0,90,12,105,115,95,110,97,109,101,115, - 112,97,99,101,90,11,116,97,105,108,95,109,111,100,117,108, - 101,114,130,0,0,0,90,5,99,97,99,104,101,90,12,99, - 97,99,104,101,95,109,111,100,117,108,101,90,9,98,97,115, - 101,95,112,97,116,104,114,221,0,0,0,114,163,0,0,0, - 90,13,105,110,105,116,95,102,105,108,101,110,97,109,101,90, - 9,102,117,108,108,95,112,97,116,104,114,162,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,178, - 0,0,0,211,4,0,0,115,70,0,0,0,0,5,4,1, - 14,1,2,1,24,1,14,1,10,1,10,1,8,1,6,2, - 6,1,6,1,10,2,6,1,4,2,8,1,12,1,16,1, - 8,1,10,1,8,1,24,4,8,2,16,1,16,1,16,1, - 12,1,8,1,10,1,12,1,6,1,12,1,12,1,8,1, - 4,1,122,20,70,105,108,101,70,105,110,100,101,114,46,102, - 105,110,100,95,115,112,101,99,99,1,0,0,0,0,0,0, - 0,9,0,0,0,14,0,0,0,67,0,0,0,115,194,0, - 0,0,124,0,106,0,125,1,121,22,116,1,160,2,124,1, - 112,22,116,1,160,3,161,0,161,1,125,2,87,0,110,30, - 4,0,116,4,116,5,116,6,102,3,107,10,114,58,1,0, - 1,0,1,0,103,0,125,2,89,0,110,2,88,0,116,7, - 106,8,160,9,100,1,161,1,115,84,116,10,124,2,131,1, - 124,0,95,11,110,78,116,10,131,0,125,3,120,64,124,2, - 68,0,93,56,125,4,124,4,160,12,100,2,161,1,92,3, - 125,5,125,6,125,7,124,6,114,138,100,3,160,13,124,5, - 124,7,160,14,161,0,161,2,125,8,110,4,124,5,125,8, - 124,3,160,15,124,8,161,1,1,0,113,96,87,0,124,3, - 124,0,95,11,116,7,106,8,160,9,116,16,161,1,114,190, - 100,4,100,5,132,0,124,2,68,0,131,1,124,0,95,17, - 100,6,83,0,41,7,122,68,70,105,108,108,32,116,104,101, - 32,99,97,99,104,101,32,111,102,32,112,111,116,101,110,116, - 105,97,108,32,109,111,100,117,108,101,115,32,97,110,100,32, - 112,97,99,107,97,103,101,115,32,102,111,114,32,116,104,105, - 115,32,100,105,114,101,99,116,111,114,121,46,114,0,0,0, - 0,114,61,0,0,0,122,5,123,125,46,123,125,99,1,0, - 0,0,0,0,0,0,2,0,0,0,4,0,0,0,83,0, - 0,0,115,20,0,0,0,104,0,124,0,93,12,125,1,124, - 1,160,0,161,0,146,2,113,4,83,0,114,4,0,0,0, - 41,1,114,92,0,0,0,41,2,114,24,0,0,0,90,2, - 102,110,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,250,9,60,115,101,116,99,111,109,112,62,32,5,0,0, - 115,2,0,0,0,6,0,122,41,70,105,108,101,70,105,110, - 100,101,114,46,95,102,105,108,108,95,99,97,99,104,101,46, - 60,108,111,99,97,108,115,62,46,60,115,101,116,99,111,109, - 112,62,78,41,18,114,37,0,0,0,114,3,0,0,0,90, - 7,108,105,115,116,100,105,114,114,47,0,0,0,114,254,0, - 0,0,218,15,80,101,114,109,105,115,115,105,111,110,69,114, - 114,111,114,218,18,78,111,116,65,68,105,114,101,99,116,111, - 114,121,69,114,114,111,114,114,8,0,0,0,114,9,0,0, - 0,114,10,0,0,0,114,7,1,0,0,114,8,1,0,0, - 114,87,0,0,0,114,50,0,0,0,114,92,0,0,0,218, - 3,97,100,100,114,11,0,0,0,114,9,1,0,0,41,9, - 114,104,0,0,0,114,37,0,0,0,90,8,99,111,110,116, - 101,110,116,115,90,21,108,111,119,101,114,95,115,117,102,102, - 105,120,95,99,111,110,116,101,110,116,115,114,243,0,0,0, - 114,102,0,0,0,114,233,0,0,0,114,221,0,0,0,90, - 8,110,101,119,95,110,97,109,101,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,114,11,1,0,0,3,5,0, - 0,115,34,0,0,0,0,2,6,1,2,1,22,1,20,3, - 10,3,12,1,12,7,6,1,10,1,16,1,4,1,18,2, - 4,1,14,1,6,1,12,1,122,22,70,105,108,101,70,105, - 110,100,101,114,46,95,102,105,108,108,95,99,97,99,104,101, - 99,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0, - 0,7,0,0,0,115,18,0,0,0,135,0,135,1,102,2, - 100,1,100,2,132,8,125,2,124,2,83,0,41,3,97,20, - 1,0,0,65,32,99,108,97,115,115,32,109,101,116,104,111, - 100,32,119,104,105,99,104,32,114,101,116,117,114,110,115,32, - 97,32,99,108,111,115,117,114,101,32,116,111,32,117,115,101, - 32,111,110,32,115,121,115,46,112,97,116,104,95,104,111,111, - 107,10,32,32,32,32,32,32,32,32,119,104,105,99,104,32, - 119,105,108,108,32,114,101,116,117,114,110,32,97,110,32,105, - 110,115,116,97,110,99,101,32,117,115,105,110,103,32,116,104, - 101,32,115,112,101,99,105,102,105,101,100,32,108,111,97,100, - 101,114,115,32,97,110,100,32,116,104,101,32,112,97,116,104, - 10,32,32,32,32,32,32,32,32,99,97,108,108,101,100,32, - 111,110,32,116,104,101,32,99,108,111,115,117,114,101,46,10, - 10,32,32,32,32,32,32,32,32,73,102,32,116,104,101,32, - 112,97,116,104,32,99,97,108,108,101,100,32,111,110,32,116, - 104,101,32,99,108,111,115,117,114,101,32,105,115,32,110,111, - 116,32,97,32,100,105,114,101,99,116,111,114,121,44,32,73, - 109,112,111,114,116,69,114,114,111,114,32,105,115,10,32,32, - 32,32,32,32,32,32,114,97,105,115,101,100,46,10,10,32, - 32,32,32,32,32,32,32,99,1,0,0,0,0,0,0,0, - 1,0,0,0,4,0,0,0,19,0,0,0,115,34,0,0, - 0,116,0,124,0,131,1,115,20,116,1,100,1,124,0,100, - 2,141,2,130,1,136,0,124,0,102,1,136,1,158,2,142, - 0,83,0,41,3,122,45,80,97,116,104,32,104,111,111,107, - 32,102,111,114,32,105,109,112,111,114,116,108,105,98,46,109, - 97,99,104,105,110,101,114,121,46,70,105,108,101,70,105,110, - 100,101,114,46,122,30,111,110,108,121,32,100,105,114,101,99, - 116,111,114,105,101,115,32,97,114,101,32,115,117,112,112,111, - 114,116,101,100,41,1,114,37,0,0,0,41,2,114,48,0, - 0,0,114,103,0,0,0,41,1,114,37,0,0,0,41,2, - 114,168,0,0,0,114,10,1,0,0,114,4,0,0,0,114, - 6,0,0,0,218,24,112,97,116,104,95,104,111,111,107,95, - 102,111,114,95,70,105,108,101,70,105,110,100,101,114,44,5, - 0,0,115,6,0,0,0,0,2,8,1,12,1,122,54,70, - 105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104, - 111,111,107,46,60,108,111,99,97,108,115,62,46,112,97,116, - 104,95,104,111,111,107,95,102,111,114,95,70,105,108,101,70, - 105,110,100,101,114,114,4,0,0,0,41,3,114,168,0,0, - 0,114,10,1,0,0,114,16,1,0,0,114,4,0,0,0, - 41,2,114,168,0,0,0,114,10,1,0,0,114,6,0,0, - 0,218,9,112,97,116,104,95,104,111,111,107,34,5,0,0, - 115,4,0,0,0,0,10,14,6,122,20,70,105,108,101,70, - 105,110,100,101,114,46,112,97,116,104,95,104,111,111,107,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,12,0,0,0,100,1,160,0,124,0,106, - 1,161,1,83,0,41,2,78,122,16,70,105,108,101,70,105, - 110,100,101,114,40,123,33,114,125,41,41,2,114,50,0,0, - 0,114,37,0,0,0,41,1,114,104,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,242,0,0, - 0,52,5,0,0,115,2,0,0,0,0,1,122,19,70,105, - 108,101,70,105,110,100,101,114,46,95,95,114,101,112,114,95, - 95,41,1,78,41,15,114,109,0,0,0,114,108,0,0,0, - 114,110,0,0,0,114,111,0,0,0,114,182,0,0,0,114, - 248,0,0,0,114,127,0,0,0,114,179,0,0,0,114,121, - 0,0,0,114,3,1,0,0,114,178,0,0,0,114,11,1, - 0,0,114,180,0,0,0,114,17,1,0,0,114,242,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,114,4,1,0,0,165,4,0,0,115,18, - 0,0,0,12,9,8,14,8,4,4,2,8,12,8,5,10, - 48,8,31,12,18,114,4,1,0,0,99,4,0,0,0,0, - 0,0,0,6,0,0,0,11,0,0,0,67,0,0,0,115, - 146,0,0,0,124,0,160,0,100,1,161,1,125,4,124,0, - 160,0,100,2,161,1,125,5,124,4,115,66,124,5,114,36, - 124,5,106,1,125,4,110,30,124,2,124,3,107,2,114,56, - 116,2,124,1,124,2,131,2,125,4,110,10,116,3,124,1, - 124,2,131,2,125,4,124,5,115,84,116,4,124,1,124,2, - 124,4,100,3,141,3,125,5,121,36,124,5,124,0,100,2, - 60,0,124,4,124,0,100,1,60,0,124,2,124,0,100,4, - 60,0,124,3,124,0,100,5,60,0,87,0,110,20,4,0, - 116,5,107,10,114,140,1,0,1,0,1,0,89,0,110,2, - 88,0,100,0,83,0,41,6,78,218,10,95,95,108,111,97, - 100,101,114,95,95,218,8,95,95,115,112,101,99,95,95,41, - 1,114,124,0,0,0,90,8,95,95,102,105,108,101,95,95, - 90,10,95,95,99,97,99,104,101,100,95,95,41,6,218,3, - 103,101,116,114,124,0,0,0,114,219,0,0,0,114,214,0, - 0,0,114,165,0,0,0,218,9,69,120,99,101,112,116,105, - 111,110,41,6,90,2,110,115,114,102,0,0,0,90,8,112, - 97,116,104,110,97,109,101,90,9,99,112,97,116,104,110,97, - 109,101,114,124,0,0,0,114,162,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,218,14,95,102,105, - 120,95,117,112,95,109,111,100,117,108,101,58,5,0,0,115, - 34,0,0,0,0,2,10,1,10,1,4,1,4,1,8,1, - 8,1,12,2,10,1,4,1,14,1,2,1,8,1,8,1, - 8,1,12,1,14,2,114,22,1,0,0,99,0,0,0,0, + 32,32,32,32,32,32,78,41,2,114,184,0,0,0,114,124, + 0,0,0,41,4,114,174,0,0,0,114,123,0,0,0,114, + 37,0,0,0,114,168,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,6,0,0,0,114,185,0,0,0,238,4,0, + 0,115,8,0,0,0,0,8,12,1,8,1,4,1,122,22, + 80,97,116,104,70,105,110,100,101,114,46,102,105,110,100,95, + 109,111,100,117,108,101,41,1,78,41,2,78,78,41,1,78, + 41,12,114,109,0,0,0,114,108,0,0,0,114,110,0,0, + 0,114,111,0,0,0,114,186,0,0,0,114,0,1,0,0, + 114,5,1,0,0,114,8,1,0,0,114,9,1,0,0,114, + 12,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,6,0, + 0,0,114,255,0,0,0,120,4,0,0,115,20,0,0,0, + 12,4,12,8,12,13,12,22,12,15,2,1,12,31,2,1, + 12,23,2,1,114,255,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,3,0,0,0,64,0,0,0,115,90, + 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,101, + 6,90,7,100,6,100,7,132,0,90,8,100,8,100,9,132, + 0,90,9,100,19,100,11,100,12,132,1,90,10,100,13,100, + 14,132,0,90,11,101,12,100,15,100,16,132,0,131,1,90, + 13,100,17,100,18,132,0,90,14,100,10,83,0,41,20,218, + 10,70,105,108,101,70,105,110,100,101,114,122,172,70,105,108, + 101,45,98,97,115,101,100,32,102,105,110,100,101,114,46,10, + 10,32,32,32,32,73,110,116,101,114,97,99,116,105,111,110, + 115,32,119,105,116,104,32,116,104,101,32,102,105,108,101,32, + 115,121,115,116,101,109,32,97,114,101,32,99,97,99,104,101, + 100,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99, + 101,44,32,98,101,105,110,103,10,32,32,32,32,114,101,102, + 114,101,115,104,101,100,32,119,104,101,110,32,116,104,101,32, + 100,105,114,101,99,116,111,114,121,32,116,104,101,32,102,105, + 110,100,101,114,32,105,115,32,104,97,110,100,108,105,110,103, + 32,104,97,115,32,98,101,101,110,32,109,111,100,105,102,105, + 101,100,46,10,10,32,32,32,32,99,2,0,0,0,0,0, + 0,0,5,0,0,0,6,0,0,0,7,0,0,0,115,88, + 0,0,0,103,0,125,3,120,40,124,2,68,0,93,32,92, + 2,137,0,125,4,124,3,160,0,135,0,102,1,100,1,100, + 2,132,8,124,4,68,0,131,1,161,1,1,0,113,10,87, + 0,124,3,124,0,95,1,124,1,112,58,100,3,124,0,95, + 2,100,6,124,0,95,3,116,4,131,0,124,0,95,5,116, + 4,131,0,124,0,95,6,100,5,83,0,41,7,122,154,73, + 110,105,116,105,97,108,105,122,101,32,119,105,116,104,32,116, + 104,101,32,112,97,116,104,32,116,111,32,115,101,97,114,99, + 104,32,111,110,32,97,110,100,32,97,32,118,97,114,105,97, + 98,108,101,32,110,117,109,98,101,114,32,111,102,10,32,32, + 32,32,32,32,32,32,50,45,116,117,112,108,101,115,32,99, + 111,110,116,97,105,110,105,110,103,32,116,104,101,32,108,111, + 97,100,101,114,32,97,110,100,32,116,104,101,32,102,105,108, + 101,32,115,117,102,102,105,120,101,115,32,116,104,101,32,108, + 111,97,100,101,114,10,32,32,32,32,32,32,32,32,114,101, + 99,111,103,110,105,122,101,115,46,99,1,0,0,0,0,0, + 0,0,2,0,0,0,3,0,0,0,51,0,0,0,115,22, + 0,0,0,124,0,93,14,125,1,124,1,136,0,102,2,86, + 0,1,0,113,2,100,0,83,0,41,1,78,114,4,0,0, + 0,41,2,114,24,0,0,0,114,229,0,0,0,41,1,114, + 124,0,0,0,114,4,0,0,0,114,6,0,0,0,114,231, + 0,0,0,11,5,0,0,115,2,0,0,0,4,0,122,38, + 70,105,108,101,70,105,110,100,101,114,46,95,95,105,110,105, + 116,95,95,46,60,108,111,99,97,108,115,62,46,60,103,101, + 110,101,120,112,114,62,114,61,0,0,0,114,31,0,0,0, + 78,114,91,0,0,0,41,7,114,149,0,0,0,218,8,95, + 108,111,97,100,101,114,115,114,37,0,0,0,218,11,95,112, + 97,116,104,95,109,116,105,109,101,218,3,115,101,116,218,11, + 95,112,97,116,104,95,99,97,99,104,101,218,19,95,114,101, + 108,97,120,101,100,95,112,97,116,104,95,99,97,99,104,101, + 41,5,114,104,0,0,0,114,37,0,0,0,218,14,108,111, + 97,100,101,114,95,100,101,116,97,105,108,115,90,7,108,111, + 97,100,101,114,115,114,170,0,0,0,114,4,0,0,0,41, + 1,114,124,0,0,0,114,6,0,0,0,114,188,0,0,0, + 5,5,0,0,115,16,0,0,0,0,4,4,1,14,1,28, + 1,6,2,10,1,6,1,8,1,122,19,70,105,108,101,70, + 105,110,100,101,114,46,95,95,105,110,105,116,95,95,99,1, + 0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,67, + 0,0,0,115,10,0,0,0,100,3,124,0,95,0,100,2, + 83,0,41,4,122,31,73,110,118,97,108,105,100,97,116,101, + 32,116,104,101,32,100,105,114,101,99,116,111,114,121,32,109, + 116,105,109,101,46,114,31,0,0,0,78,114,91,0,0,0, + 41,1,114,15,1,0,0,41,1,114,104,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,6,0,0,0,114,0,1, + 0,0,19,5,0,0,115,2,0,0,0,0,2,122,28,70, + 105,108,101,70,105,110,100,101,114,46,105,110,118,97,108,105, + 100,97,116,101,95,99,97,99,104,101,115,99,2,0,0,0, 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, - 115,38,0,0,0,116,0,116,1,160,2,161,0,102,2,125, - 0,116,3,116,4,102,2,125,1,116,5,116,6,102,2,125, - 2,124,0,124,1,124,2,103,3,83,0,41,1,122,95,82, - 101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102, - 32,102,105,108,101,45,98,97,115,101,100,32,109,111,100,117, - 108,101,32,108,111,97,100,101,114,115,46,10,10,32,32,32, - 32,69,97,99,104,32,105,116,101,109,32,105,115,32,97,32, - 116,117,112,108,101,32,40,108,111,97,100,101,114,44,32,115, - 117,102,102,105,120,101,115,41,46,10,32,32,32,32,41,7, - 114,220,0,0,0,114,143,0,0,0,218,18,101,120,116,101, - 110,115,105,111,110,95,115,117,102,102,105,120,101,115,114,214, - 0,0,0,114,88,0,0,0,114,219,0,0,0,114,78,0, - 0,0,41,3,90,10,101,120,116,101,110,115,105,111,110,115, - 90,6,115,111,117,114,99,101,90,8,98,121,116,101,99,111, - 100,101,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,159,0,0,0,81,5,0,0,115,8,0,0,0,0, - 5,12,1,8,1,8,1,114,159,0,0,0,99,1,0,0, - 0,0,0,0,0,12,0,0,0,12,0,0,0,67,0,0, - 0,115,156,1,0,0,124,0,97,0,116,0,106,1,97,1, - 116,0,106,2,97,2,116,1,106,3,116,4,25,0,125,1, - 120,56,100,26,68,0,93,48,125,2,124,2,116,1,106,3, - 107,7,114,58,116,0,160,5,124,2,161,1,125,3,110,10, - 116,1,106,3,124,2,25,0,125,3,116,6,124,1,124,2, - 124,3,131,3,1,0,113,32,87,0,100,5,100,6,103,1, - 102,2,100,7,100,8,100,6,103,2,102,2,102,2,125,4, - 120,118,124,4,68,0,93,102,92,2,125,5,125,6,116,7, - 100,9,100,10,132,0,124,6,68,0,131,1,131,1,115,142, - 116,8,130,1,124,6,100,11,25,0,125,7,124,5,116,1, - 106,3,107,6,114,174,116,1,106,3,124,5,25,0,125,8, - 80,0,113,112,121,16,116,0,160,5,124,5,161,1,125,8, - 80,0,87,0,113,112,4,0,116,9,107,10,114,212,1,0, - 1,0,1,0,119,112,89,0,113,112,88,0,113,112,87,0, - 116,9,100,12,131,1,130,1,116,6,124,1,100,13,124,8, - 131,3,1,0,116,6,124,1,100,14,124,7,131,3,1,0, - 116,6,124,1,100,15,100,16,160,10,124,6,161,1,131,3, - 1,0,116,0,160,5,100,17,161,1,125,9,116,6,124,1, - 100,17,124,9,131,3,1,0,116,0,160,5,100,18,161,1, - 125,10,116,6,124,1,100,18,124,10,131,3,1,0,124,5, - 100,7,107,2,144,1,114,88,116,0,160,5,100,19,161,1, - 125,11,116,6,124,1,100,20,124,11,131,3,1,0,116,6, - 124,1,100,21,116,11,131,0,131,3,1,0,116,12,160,13, - 116,2,160,14,161,0,161,1,1,0,124,5,100,7,107,2, - 144,1,114,152,116,15,160,16,100,22,161,1,1,0,100,23, - 116,12,107,6,144,1,114,152,100,24,116,17,95,18,100,25, - 83,0,41,27,122,205,83,101,116,117,112,32,116,104,101,32, - 112,97,116,104,45,98,97,115,101,100,32,105,109,112,111,114, - 116,101,114,115,32,102,111,114,32,105,109,112,111,114,116,108, - 105,98,32,98,121,32,105,109,112,111,114,116,105,110,103,32, - 110,101,101,100,101,100,10,32,32,32,32,98,117,105,108,116, - 45,105,110,32,109,111,100,117,108,101,115,32,97,110,100,32, - 105,110,106,101,99,116,105,110,103,32,116,104,101,109,32,105, - 110,116,111,32,116,104,101,32,103,108,111,98,97,108,32,110, - 97,109,101,115,112,97,99,101,46,10,10,32,32,32,32,79, - 116,104,101,114,32,99,111,109,112,111,110,101,110,116,115,32, - 97,114,101,32,101,120,116,114,97,99,116,101,100,32,102,114, - 111,109,32,116,104,101,32,99,111,114,101,32,98,111,111,116, - 115,116,114,97,112,32,109,111,100,117,108,101,46,10,10,32, - 32,32,32,114,52,0,0,0,114,63,0,0,0,218,8,98, - 117,105,108,116,105,110,115,114,140,0,0,0,90,5,112,111, - 115,105,120,250,1,47,90,2,110,116,250,1,92,99,1,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,115,0, - 0,0,115,26,0,0,0,124,0,93,18,125,1,116,0,124, - 1,131,1,100,0,107,2,86,0,1,0,113,2,100,1,83, - 0,41,2,114,31,0,0,0,78,41,1,114,33,0,0,0, - 41,2,114,24,0,0,0,114,81,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,114,223,0,0,0, - 117,5,0,0,115,2,0,0,0,4,0,122,25,95,115,101, - 116,117,112,46,60,108,111,99,97,108,115,62,46,60,103,101, - 110,101,120,112,114,62,114,62,0,0,0,122,30,105,109,112, - 111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32, - 112,111,115,105,120,32,111,114,32,110,116,114,3,0,0,0, - 114,27,0,0,0,114,23,0,0,0,114,32,0,0,0,90, - 7,95,116,104,114,101,97,100,90,8,95,119,101,97,107,114, - 101,102,90,6,119,105,110,114,101,103,114,167,0,0,0,114, - 7,0,0,0,122,4,46,112,121,119,122,6,95,100,46,112, - 121,100,84,78,41,4,114,52,0,0,0,114,63,0,0,0, - 114,24,1,0,0,114,140,0,0,0,41,19,114,118,0,0, - 0,114,8,0,0,0,114,143,0,0,0,114,235,0,0,0, - 114,109,0,0,0,90,18,95,98,117,105,108,116,105,110,95, - 102,114,111,109,95,110,97,109,101,114,113,0,0,0,218,3, - 97,108,108,218,14,65,115,115,101,114,116,105,111,110,69,114, - 114,111,114,114,103,0,0,0,114,28,0,0,0,114,13,0, - 0,0,114,225,0,0,0,114,147,0,0,0,114,23,1,0, - 0,114,88,0,0,0,114,161,0,0,0,114,166,0,0,0, - 114,170,0,0,0,41,12,218,17,95,98,111,111,116,115,116, - 114,97,112,95,109,111,100,117,108,101,90,11,115,101,108,102, - 95,109,111,100,117,108,101,90,12,98,117,105,108,116,105,110, - 95,110,97,109,101,90,14,98,117,105,108,116,105,110,95,109, - 111,100,117,108,101,90,10,111,115,95,100,101,116,97,105,108, - 115,90,10,98,117,105,108,116,105,110,95,111,115,114,23,0, - 0,0,114,27,0,0,0,90,9,111,115,95,109,111,100,117, - 108,101,90,13,116,104,114,101,97,100,95,109,111,100,117,108, - 101,90,14,119,101,97,107,114,101,102,95,109,111,100,117,108, - 101,90,13,119,105,110,114,101,103,95,109,111,100,117,108,101, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218, - 6,95,115,101,116,117,112,92,5,0,0,115,76,0,0,0, - 0,8,4,1,6,1,6,3,10,1,10,1,10,1,12,2, - 10,1,16,3,22,1,14,2,22,1,8,1,10,1,10,1, - 4,2,2,1,10,1,6,1,14,1,12,2,8,1,12,1, - 12,1,18,3,10,1,12,3,10,1,12,3,10,1,10,1, - 12,3,14,1,14,1,10,1,10,1,10,1,114,30,1,0, - 0,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,67,0,0,0,115,50,0,0,0,116,0,124,0,131, - 1,1,0,116,1,131,0,125,1,116,2,106,3,160,4,116, - 5,106,6,124,1,142,0,103,1,161,1,1,0,116,2,106, - 7,160,8,116,9,161,1,1,0,100,1,83,0,41,2,122, - 41,73,110,115,116,97,108,108,32,116,104,101,32,112,97,116, - 104,45,98,97,115,101,100,32,105,109,112,111,114,116,32,99, - 111,109,112,111,110,101,110,116,115,46,78,41,10,114,30,1, - 0,0,114,159,0,0,0,114,8,0,0,0,114,252,0,0, - 0,114,147,0,0,0,114,4,1,0,0,114,17,1,0,0, - 218,9,109,101,116,97,95,112,97,116,104,114,161,0,0,0, - 114,247,0,0,0,41,2,114,29,1,0,0,90,17,115,117, - 112,112,111,114,116,101,100,95,108,111,97,100,101,114,115,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,8, - 95,105,110,115,116,97,108,108,156,5,0,0,115,8,0,0, - 0,0,2,8,1,6,1,20,1,114,32,1,0,0,41,1, - 114,0,0,0,0,41,2,114,1,0,0,0,114,2,0,0, - 0,41,1,114,49,0,0,0,41,1,78,41,3,78,78,78, - 41,3,78,78,78,41,2,114,62,0,0,0,114,62,0,0, - 0,41,1,78,41,1,78,41,58,114,111,0,0,0,114,12, - 0,0,0,90,37,95,67,65,83,69,95,73,78,83,69,78, - 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, - 95,66,89,84,69,83,95,75,69,89,114,11,0,0,0,114, - 13,0,0,0,114,19,0,0,0,114,21,0,0,0,114,30, - 0,0,0,114,40,0,0,0,114,41,0,0,0,114,45,0, - 0,0,114,46,0,0,0,114,48,0,0,0,114,58,0,0, - 0,218,4,116,121,112,101,218,8,95,95,99,111,100,101,95, - 95,114,142,0,0,0,114,17,0,0,0,114,132,0,0,0, - 114,16,0,0,0,114,20,0,0,0,90,17,95,82,65,87, - 95,77,65,71,73,67,95,78,85,77,66,69,82,114,77,0, - 0,0,114,76,0,0,0,114,88,0,0,0,114,78,0,0, - 0,90,23,68,69,66,85,71,95,66,89,84,69,67,79,68, - 69,95,83,85,70,70,73,88,69,83,90,27,79,80,84,73, - 77,73,90,69,68,95,66,89,84,69,67,79,68,69,95,83, - 85,70,70,73,88,69,83,114,83,0,0,0,114,89,0,0, - 0,114,95,0,0,0,114,99,0,0,0,114,101,0,0,0, - 114,120,0,0,0,114,127,0,0,0,114,139,0,0,0,114, - 145,0,0,0,114,148,0,0,0,114,153,0,0,0,218,6, - 111,98,106,101,99,116,114,160,0,0,0,114,165,0,0,0, - 114,166,0,0,0,114,181,0,0,0,114,191,0,0,0,114, - 206,0,0,0,114,214,0,0,0,114,219,0,0,0,114,225, - 0,0,0,114,220,0,0,0,114,226,0,0,0,114,245,0, - 0,0,114,247,0,0,0,114,4,1,0,0,114,22,1,0, - 0,114,159,0,0,0,114,30,1,0,0,114,32,1,0,0, - 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,8,60,109,111,100,117,108,101,62,24,0, - 0,0,115,108,0,0,0,4,0,4,1,4,1,2,1,6, - 3,8,17,8,5,8,5,8,6,8,12,8,10,8,9,8, - 5,8,7,10,22,10,125,16,1,12,2,4,1,4,2,6, - 2,6,2,8,2,16,45,8,34,8,19,8,12,8,12,8, - 28,8,17,10,55,10,12,10,10,8,14,6,3,4,1,14, - 67,14,64,14,29,16,110,14,41,18,45,18,16,4,3,18, - 53,14,60,14,42,14,127,0,5,14,127,0,22,10,23,8, - 11,8,64, + 115,42,0,0,0,124,0,160,0,124,1,161,1,125,2,124, + 2,100,1,107,8,114,26,100,1,103,0,102,2,83,0,124, + 2,106,1,124,2,106,2,112,38,103,0,102,2,83,0,41, + 2,122,197,84,114,121,32,116,111,32,102,105,110,100,32,97, + 32,108,111,97,100,101,114,32,102,111,114,32,116,104,101,32, + 115,112,101,99,105,102,105,101,100,32,109,111,100,117,108,101, + 44,32,111,114,32,116,104,101,32,110,97,109,101,115,112,97, + 99,101,10,32,32,32,32,32,32,32,32,112,97,99,107,97, + 103,101,32,112,111,114,116,105,111,110,115,46,32,82,101,116, + 117,114,110,115,32,40,108,111,97,100,101,114,44,32,108,105, + 115,116,45,111,102,45,112,111,114,116,105,111,110,115,41,46, + 10,10,32,32,32,32,32,32,32,32,84,104,105,115,32,109, + 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,46,32,32,85,115,101,32,102,105,110,100,95,115, + 112,101,99,40,41,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,32,32,32,32,78,41,3,114,184,0,0,0, + 114,124,0,0,0,114,160,0,0,0,41,3,114,104,0,0, + 0,114,123,0,0,0,114,168,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,6,0,0,0,114,121,0,0,0,25, + 5,0,0,115,8,0,0,0,0,7,10,1,8,1,8,1, + 122,22,70,105,108,101,70,105,110,100,101,114,46,102,105,110, + 100,95,108,111,97,100,101,114,99,6,0,0,0,0,0,0, + 0,7,0,0,0,6,0,0,0,67,0,0,0,115,26,0, + 0,0,124,1,124,2,124,3,131,2,125,6,116,0,124,2, + 124,3,124,6,124,4,100,1,141,4,83,0,41,2,78,41, + 2,114,124,0,0,0,114,160,0,0,0,41,1,114,171,0, + 0,0,41,7,114,104,0,0,0,114,169,0,0,0,114,123, + 0,0,0,114,37,0,0,0,90,4,115,109,115,108,114,183, + 0,0,0,114,124,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,114,12,1,0,0,37,5,0,0, + 115,6,0,0,0,0,1,10,1,8,1,122,20,70,105,108, + 101,70,105,110,100,101,114,46,95,103,101,116,95,115,112,101, + 99,78,99,3,0,0,0,0,0,0,0,14,0,0,0,16, + 0,0,0,67,0,0,0,115,98,1,0,0,100,1,125,3, + 124,1,160,0,100,2,161,1,100,3,25,0,125,4,121,24, + 116,1,124,0,106,2,112,34,116,3,160,4,161,0,131,1, + 106,5,125,5,87,0,110,24,4,0,116,6,107,10,114,66, + 1,0,1,0,1,0,100,10,125,5,89,0,110,2,88,0, + 124,5,124,0,106,7,107,3,114,92,124,0,160,8,161,0, + 1,0,124,5,124,0,95,7,116,9,131,0,114,114,124,0, + 106,10,125,6,124,4,160,11,161,0,125,7,110,10,124,0, + 106,12,125,6,124,4,125,7,124,7,124,6,107,6,114,218, + 116,13,124,0,106,2,124,4,131,2,125,8,120,72,124,0, + 106,14,68,0,93,54,92,2,125,9,125,10,100,5,124,9, + 23,0,125,11,116,13,124,8,124,11,131,2,125,12,116,15, + 124,12,131,1,114,152,124,0,160,16,124,10,124,1,124,12, + 124,8,103,1,124,2,161,5,83,0,113,152,87,0,116,17, + 124,8,131,1,125,3,120,88,124,0,106,14,68,0,93,78, + 92,2,125,9,125,10,116,13,124,0,106,2,124,4,124,9, + 23,0,131,2,125,12,116,18,106,19,100,6,124,12,100,3, + 100,7,141,3,1,0,124,7,124,9,23,0,124,6,107,6, + 114,226,116,15,124,12,131,1,114,226,124,0,160,16,124,10, + 124,1,124,12,100,8,124,2,161,5,83,0,113,226,87,0, + 124,3,144,1,114,94,116,18,160,19,100,9,124,8,161,2, + 1,0,116,18,160,20,124,1,100,8,161,2,125,13,124,8, + 103,1,124,13,95,21,124,13,83,0,100,8,83,0,41,11, + 122,111,84,114,121,32,116,111,32,102,105,110,100,32,97,32, + 115,112,101,99,32,102,111,114,32,116,104,101,32,115,112,101, + 99,105,102,105,101,100,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,82,101,116,117,114,110,115,32, + 116,104,101,32,109,97,116,99,104,105,110,103,32,115,112,101, + 99,44,32,111,114,32,78,111,110,101,32,105,102,32,110,111, + 116,32,102,111,117,110,100,46,10,32,32,32,32,32,32,32, + 32,70,114,61,0,0,0,114,59,0,0,0,114,31,0,0, + 0,114,188,0,0,0,122,9,116,114,121,105,110,103,32,123, + 125,41,1,90,9,118,101,114,98,111,115,105,116,121,78,122, + 25,112,111,115,115,105,98,108,101,32,110,97,109,101,115,112, + 97,99,101,32,102,111,114,32,123,125,114,91,0,0,0,41, + 22,114,34,0,0,0,114,41,0,0,0,114,37,0,0,0, + 114,3,0,0,0,114,47,0,0,0,114,223,0,0,0,114, + 42,0,0,0,114,15,1,0,0,218,11,95,102,105,108,108, + 95,99,97,99,104,101,114,7,0,0,0,114,18,1,0,0, + 114,92,0,0,0,114,17,1,0,0,114,30,0,0,0,114, + 14,1,0,0,114,46,0,0,0,114,12,1,0,0,114,48, + 0,0,0,114,118,0,0,0,114,132,0,0,0,114,164,0, + 0,0,114,160,0,0,0,41,14,114,104,0,0,0,114,123, + 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,151,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,169,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,168,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, + 114,184,0,0,0,42,5,0,0,115,70,0,0,0,0,5, + 4,1,14,1,2,1,24,1,14,1,10,1,10,1,8,1, + 6,2,6,1,6,1,10,2,6,1,4,2,8,1,12,1, + 16,1,8,1,10,1,8,1,24,4,8,2,16,1,16,1, + 16,1,12,1,8,1,10,1,12,1,6,1,12,1,12,1, + 8,1,4,1,122,20,70,105,108,101,70,105,110,100,101,114, + 46,102,105,110,100,95,115,112,101,99,99,1,0,0,0,0, + 0,0,0,9,0,0,0,14,0,0,0,67,0,0,0,115, + 194,0,0,0,124,0,106,0,125,1,121,22,116,1,160,2, + 124,1,112,22,116,1,160,3,161,0,161,1,125,2,87,0, + 110,30,4,0,116,4,116,5,116,6,102,3,107,10,114,58, + 1,0,1,0,1,0,103,0,125,2,89,0,110,2,88,0, + 116,7,106,8,160,9,100,1,161,1,115,84,116,10,124,2, + 131,1,124,0,95,11,110,78,116,10,131,0,125,3,120,64, + 124,2,68,0,93,56,125,4,124,4,160,12,100,2,161,1, + 92,3,125,5,125,6,125,7,124,6,114,138,100,3,160,13, + 124,5,124,7,160,14,161,0,161,2,125,8,110,4,124,5, + 125,8,124,3,160,15,124,8,161,1,1,0,113,96,87,0, + 124,3,124,0,95,11,116,7,106,8,160,9,116,16,161,1, + 114,190,100,4,100,5,132,0,124,2,68,0,131,1,124,0, + 95,17,100,6,83,0,41,7,122,68,70,105,108,108,32,116, + 104,101,32,99,97,99,104,101,32,111,102,32,112,111,116,101, + 110,116,105,97,108,32,109,111,100,117,108,101,115,32,97,110, + 100,32,112,97,99,107,97,103,101,115,32,102,111,114,32,116, + 104,105,115,32,100,105,114,101,99,116,111,114,121,46,114,0, + 0,0,0,114,61,0,0,0,122,5,123,125,46,123,125,99, + 1,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, + 83,0,0,0,115,20,0,0,0,104,0,124,0,93,12,125, + 1,124,1,160,0,161,0,146,2,113,4,83,0,114,4,0, + 0,0,41,1,114,92,0,0,0,41,2,114,24,0,0,0, + 90,2,102,110,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,250,9,60,115,101,116,99,111,109,112,62,119,5, + 0,0,115,2,0,0,0,6,0,122,41,70,105,108,101,70, + 105,110,100,101,114,46,95,102,105,108,108,95,99,97,99,104, + 101,46,60,108,111,99,97,108,115,62,46,60,115,101,116,99, + 111,109,112,62,78,41,18,114,37,0,0,0,114,3,0,0, + 0,90,7,108,105,115,116,100,105,114,114,47,0,0,0,114, + 6,1,0,0,218,15,80,101,114,109,105,115,115,105,111,110, + 69,114,114,111,114,218,18,78,111,116,65,68,105,114,101,99, + 116,111,114,121,69,114,114,111,114,114,8,0,0,0,114,9, + 0,0,0,114,10,0,0,0,114,16,1,0,0,114,17,1, + 0,0,114,87,0,0,0,114,50,0,0,0,114,92,0,0, + 0,218,3,97,100,100,114,11,0,0,0,114,18,1,0,0, + 41,9,114,104,0,0,0,114,37,0,0,0,90,8,99,111, + 110,116,101,110,116,115,90,21,108,111,119,101,114,95,115,117, + 102,102,105,120,95,99,111,110,116,101,110,116,115,114,251,0, + 0,0,114,102,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,6,0,0,0,114,20,1,0,0,90, + 5,0,0,115,34,0,0,0,0,2,6,1,2,1,22,1, + 20,3,10,3,12,1,12,7,6,1,10,1,16,1,4,1, + 18,2,4,1,14,1,6,1,12,1,122,22,70,105,108,101, + 70,105,110,100,101,114,46,95,102,105,108,108,95,99,97,99, + 104,101,99,1,0,0,0,0,0,0,0,3,0,0,0,3, + 0,0,0,7,0,0,0,115,18,0,0,0,135,0,135,1, + 102,2,100,1,100,2,132,8,125,2,124,2,83,0,41,3, + 97,20,1,0,0,65,32,99,108,97,115,115,32,109,101,116, + 104,111,100,32,119,104,105,99,104,32,114,101,116,117,114,110, + 115,32,97,32,99,108,111,115,117,114,101,32,116,111,32,117, + 115,101,32,111,110,32,115,121,115,46,112,97,116,104,95,104, + 111,111,107,10,32,32,32,32,32,32,32,32,119,104,105,99, + 104,32,119,105,108,108,32,114,101,116,117,114,110,32,97,110, + 32,105,110,115,116,97,110,99,101,32,117,115,105,110,103,32, + 116,104,101,32,115,112,101,99,105,102,105,101,100,32,108,111, + 97,100,101,114,115,32,97,110,100,32,116,104,101,32,112,97, + 116,104,10,32,32,32,32,32,32,32,32,99,97,108,108,101, + 100,32,111,110,32,116,104,101,32,99,108,111,115,117,114,101, + 46,10,10,32,32,32,32,32,32,32,32,73,102,32,116,104, + 101,32,112,97,116,104,32,99,97,108,108,101,100,32,111,110, + 32,116,104,101,32,99,108,111,115,117,114,101,32,105,115,32, + 110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,44, + 32,73,109,112,111,114,116,69,114,114,111,114,32,105,115,10, + 32,32,32,32,32,32,32,32,114,97,105,115,101,100,46,10, + 10,32,32,32,32,32,32,32,32,99,1,0,0,0,0,0, + 0,0,1,0,0,0,4,0,0,0,19,0,0,0,115,34, + 0,0,0,116,0,124,0,131,1,115,20,116,1,100,1,124, + 0,100,2,141,2,130,1,136,0,124,0,102,1,136,1,158, + 2,142,0,83,0,41,3,122,45,80,97,116,104,32,104,111, + 111,107,32,102,111,114,32,105,109,112,111,114,116,108,105,98, + 46,109,97,99,104,105,110,101,114,121,46,70,105,108,101,70, + 105,110,100,101,114,46,122,30,111,110,108,121,32,100,105,114, + 101,99,116,111,114,105,101,115,32,97,114,101,32,115,117,112, + 112,111,114,116,101,100,41,1,114,37,0,0,0,41,2,114, + 48,0,0,0,114,103,0,0,0,41,1,114,37,0,0,0, + 41,2,114,174,0,0,0,114,19,1,0,0,114,4,0,0, + 0,114,6,0,0,0,218,24,112,97,116,104,95,104,111,111, + 107,95,102,111,114,95,70,105,108,101,70,105,110,100,101,114, + 131,5,0,0,115,6,0,0,0,0,2,8,1,12,1,122, + 54,70,105,108,101,70,105,110,100,101,114,46,112,97,116,104, + 95,104,111,111,107,46,60,108,111,99,97,108,115,62,46,112, + 97,116,104,95,104,111,111,107,95,102,111,114,95,70,105,108, + 101,70,105,110,100,101,114,114,4,0,0,0,41,3,114,174, + 0,0,0,114,19,1,0,0,114,25,1,0,0,114,4,0, + 0,0,41,2,114,174,0,0,0,114,19,1,0,0,114,6, + 0,0,0,218,9,112,97,116,104,95,104,111,111,107,121,5, + 0,0,115,4,0,0,0,0,10,14,6,122,20,70,105,108, + 101,70,105,110,100,101,114,46,112,97,116,104,95,104,111,111, + 107,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, + 0,0,67,0,0,0,115,12,0,0,0,100,1,160,0,124, + 0,106,1,161,1,83,0,41,2,78,122,16,70,105,108,101, + 70,105,110,100,101,114,40,123,33,114,125,41,41,2,114,50, + 0,0,0,114,37,0,0,0,41,1,114,104,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,250, + 0,0,0,139,5,0,0,115,2,0,0,0,0,1,122,19, + 70,105,108,101,70,105,110,100,101,114,46,95,95,114,101,112, + 114,95,95,41,1,78,41,15,114,109,0,0,0,114,108,0, + 0,0,114,110,0,0,0,114,111,0,0,0,114,188,0,0, + 0,114,0,1,0,0,114,127,0,0,0,114,185,0,0,0, + 114,121,0,0,0,114,12,1,0,0,114,184,0,0,0,114, + 20,1,0,0,114,186,0,0,0,114,26,1,0,0,114,250, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,114,13,1,0,0,252,4,0,0, + 115,18,0,0,0,12,9,8,14,8,4,4,2,8,12,8, + 5,10,48,8,31,12,18,114,13,1,0,0,99,4,0,0, + 0,0,0,0,0,6,0,0,0,11,0,0,0,67,0,0, + 0,115,146,0,0,0,124,0,160,0,100,1,161,1,125,4, + 124,0,160,0,100,2,161,1,125,5,124,4,115,66,124,5, + 114,36,124,5,106,1,125,4,110,30,124,2,124,3,107,2, + 114,56,116,2,124,1,124,2,131,2,125,4,110,10,116,3, + 124,1,124,2,131,2,125,4,124,5,115,84,116,4,124,1, + 124,2,124,4,100,3,141,3,125,5,121,36,124,5,124,0, + 100,2,60,0,124,4,124,0,100,1,60,0,124,2,124,0, + 100,4,60,0,124,3,124,0,100,5,60,0,87,0,110,20, + 4,0,116,5,107,10,114,140,1,0,1,0,1,0,89,0, + 110,2,88,0,100,0,83,0,41,6,78,218,10,95,95,108, + 111,97,100,101,114,95,95,218,8,95,95,115,112,101,99,95, + 95,41,1,114,124,0,0,0,90,8,95,95,102,105,108,101, + 95,95,90,10,95,95,99,97,99,104,101,100,95,95,41,6, + 218,3,103,101,116,114,124,0,0,0,114,227,0,0,0,114, + 222,0,0,0,114,171,0,0,0,218,9,69,120,99,101,112, + 116,105,111,110,41,6,90,2,110,115,114,102,0,0,0,90, + 8,112,97,116,104,110,97,109,101,90,9,99,112,97,116,104, + 110,97,109,101,114,124,0,0,0,114,168,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,6,0,0,0,218,14,95, + 102,105,120,95,117,112,95,109,111,100,117,108,101,145,5,0, + 0,115,34,0,0,0,0,2,10,1,10,1,4,1,4,1, + 8,1,8,1,12,2,10,1,4,1,14,1,2,1,8,1, + 8,1,8,1,12,1,14,2,114,31,1,0,0,99,0,0, + 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, + 0,0,115,38,0,0,0,116,0,116,1,160,2,161,0,102, + 2,125,0,116,3,116,4,102,2,125,1,116,5,116,6,102, + 2,125,2,124,0,124,1,124,2,103,3,83,0,41,1,122, + 95,82,101,116,117,114,110,115,32,97,32,108,105,115,116,32, + 111,102,32,102,105,108,101,45,98,97,115,101,100,32,109,111, + 100,117,108,101,32,108,111,97,100,101,114,115,46,10,10,32, + 32,32,32,69,97,99,104,32,105,116,101,109,32,105,115,32, + 97,32,116,117,112,108,101,32,40,108,111,97,100,101,114,44, + 32,115,117,102,102,105,120,101,115,41,46,10,32,32,32,32, + 41,7,114,228,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,222,0,0,0,114,88,0,0,0,114,227,0,0,0,114, + 78,0,0,0,41,3,90,10,101,120,116,101,110,115,105,111, + 110,115,90,6,115,111,117,114,99,101,90,8,98,121,116,101, + 99,111,100,101,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,114,165,0,0,0,168,5,0,0,115,8,0,0, + 0,0,5,12,1,8,1,8,1,114,165,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,156,1,0,0,124,0,97,0,116,0,106,1, + 97,1,116,0,106,2,97,2,116,1,106,3,116,4,25,0, + 125,1,120,56,100,26,68,0,93,48,125,2,124,2,116,1, + 106,3,107,7,114,58,116,0,160,5,124,2,161,1,125,3, + 110,10,116,1,106,3,124,2,25,0,125,3,116,6,124,1, + 124,2,124,3,131,3,1,0,113,32,87,0,100,5,100,6, + 103,1,102,2,100,7,100,8,100,6,103,2,102,2,102,2, + 125,4,120,118,124,4,68,0,93,102,92,2,125,5,125,6, + 116,7,100,9,100,10,132,0,124,6,68,0,131,1,131,1, + 115,142,116,8,130,1,124,6,100,11,25,0,125,7,124,5, + 116,1,106,3,107,6,114,174,116,1,106,3,124,5,25,0, + 125,8,80,0,113,112,121,16,116,0,160,5,124,5,161,1, + 125,8,80,0,87,0,113,112,4,0,116,9,107,10,114,212, + 1,0,1,0,1,0,119,112,89,0,113,112,88,0,113,112, + 87,0,116,9,100,12,131,1,130,1,116,6,124,1,100,13, + 124,8,131,3,1,0,116,6,124,1,100,14,124,7,131,3, + 1,0,116,6,124,1,100,15,100,16,160,10,124,6,161,1, + 131,3,1,0,116,0,160,5,100,17,161,1,125,9,116,6, + 124,1,100,17,124,9,131,3,1,0,116,0,160,5,100,18, + 161,1,125,10,116,6,124,1,100,18,124,10,131,3,1,0, + 124,5,100,7,107,2,144,1,114,88,116,0,160,5,100,19, + 161,1,125,11,116,6,124,1,100,20,124,11,131,3,1,0, + 116,6,124,1,100,21,116,11,131,0,131,3,1,0,116,12, + 160,13,116,2,160,14,161,0,161,1,1,0,124,5,100,7, + 107,2,144,1,114,152,116,15,160,16,100,22,161,1,1,0, + 100,23,116,12,107,6,144,1,114,152,100,24,116,17,95,18, + 100,25,83,0,41,27,122,205,83,101,116,117,112,32,116,104, + 101,32,112,97,116,104,45,98,97,115,101,100,32,105,109,112, + 111,114,116,101,114,115,32,102,111,114,32,105,109,112,111,114, + 116,108,105,98,32,98,121,32,105,109,112,111,114,116,105,110, + 103,32,110,101,101,100,101,100,10,32,32,32,32,98,117,105, + 108,116,45,105,110,32,109,111,100,117,108,101,115,32,97,110, + 100,32,105,110,106,101,99,116,105,110,103,32,116,104,101,109, + 32,105,110,116,111,32,116,104,101,32,103,108,111,98,97,108, + 32,110,97,109,101,115,112,97,99,101,46,10,10,32,32,32, + 32,79,116,104,101,114,32,99,111,109,112,111,110,101,110,116, + 115,32,97,114,101,32,101,120,116,114,97,99,116,101,100,32, + 102,114,111,109,32,116,104,101,32,99,111,114,101,32,98,111, + 111,116,115,116,114,97,112,32,109,111,100,117,108,101,46,10, + 10,32,32,32,32,114,52,0,0,0,114,63,0,0,0,218, + 8,98,117,105,108,116,105,110,115,114,142,0,0,0,90,5, + 112,111,115,105,120,250,1,47,90,2,110,116,250,1,92,99, + 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 115,0,0,0,115,26,0,0,0,124,0,93,18,125,1,116, + 0,124,1,131,1,100,0,107,2,86,0,1,0,113,2,100, + 1,83,0,41,2,114,31,0,0,0,78,41,1,114,33,0, + 0,0,41,2,114,24,0,0,0,114,81,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,6,0,0,0,114,231,0, + 0,0,204,5,0,0,115,2,0,0,0,4,0,122,25,95, + 115,101,116,117,112,46,60,108,111,99,97,108,115,62,46,60, + 103,101,110,101,120,112,114,62,114,62,0,0,0,122,30,105, + 109,112,111,114,116,108,105,98,32,114,101,113,117,105,114,101, + 115,32,112,111,115,105,120,32,111,114,32,110,116,114,3,0, + 0,0,114,27,0,0,0,114,23,0,0,0,114,32,0,0, + 0,90,7,95,116,104,114,101,97,100,90,8,95,119,101,97, + 107,114,101,102,90,6,119,105,110,114,101,103,114,173,0,0, + 0,114,7,0,0,0,122,4,46,112,121,119,122,6,95,100, + 46,112,121,100,84,78,41,4,114,52,0,0,0,114,63,0, + 0,0,114,33,1,0,0,114,142,0,0,0,41,19,114,118, + 0,0,0,114,8,0,0,0,114,145,0,0,0,114,243,0, + 0,0,114,109,0,0,0,90,18,95,98,117,105,108,116,105, + 110,95,102,114,111,109,95,110,97,109,101,114,113,0,0,0, + 218,3,97,108,108,114,153,0,0,0,114,103,0,0,0,114, + 28,0,0,0,114,13,0,0,0,114,233,0,0,0,114,149, + 0,0,0,114,32,1,0,0,114,88,0,0,0,114,167,0, + 0,0,114,172,0,0,0,114,176,0,0,0,41,12,218,17, + 95,98,111,111,116,115,116,114,97,112,95,109,111,100,117,108, + 101,90,11,115,101,108,102,95,109,111,100,117,108,101,90,12, + 98,117,105,108,116,105,110,95,110,97,109,101,90,14,98,117, + 105,108,116,105,110,95,109,111,100,117,108,101,90,10,111,115, + 95,100,101,116,97,105,108,115,90,10,98,117,105,108,116,105, + 110,95,111,115,114,23,0,0,0,114,27,0,0,0,90,9, + 111,115,95,109,111,100,117,108,101,90,13,116,104,114,101,97, + 100,95,109,111,100,117,108,101,90,14,119,101,97,107,114,101, + 102,95,109,111,100,117,108,101,90,13,119,105,110,114,101,103, + 95,109,111,100,117,108,101,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,218,6,95,115,101,116,117,112,179,5, + 0,0,115,76,0,0,0,0,8,4,1,6,1,6,3,10, + 1,10,1,10,1,12,2,10,1,16,3,22,1,14,2,22, + 1,8,1,10,1,10,1,4,2,2,1,10,1,6,1,14, + 1,12,2,8,1,12,1,12,1,18,3,10,1,12,3,10, + 1,12,3,10,1,10,1,12,3,14,1,14,1,10,1,10, + 1,10,1,114,38,1,0,0,99,1,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,67,0,0,0,115,50,0, + 0,0,116,0,124,0,131,1,1,0,116,1,131,0,125,1, + 116,2,106,3,160,4,116,5,106,6,124,1,142,0,103,1, + 161,1,1,0,116,2,106,7,160,8,116,9,161,1,1,0, + 100,1,83,0,41,2,122,41,73,110,115,116,97,108,108,32, + 116,104,101,32,112,97,116,104,45,98,97,115,101,100,32,105, + 109,112,111,114,116,32,99,111,109,112,111,110,101,110,116,115, + 46,78,41,10,114,38,1,0,0,114,165,0,0,0,114,8, + 0,0,0,114,4,1,0,0,114,149,0,0,0,114,13,1, + 0,0,114,26,1,0,0,218,9,109,101,116,97,95,112,97, + 116,104,114,167,0,0,0,114,255,0,0,0,41,2,114,37, + 1,0,0,90,17,115,117,112,112,111,114,116,101,100,95,108, + 111,97,100,101,114,115,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,218,8,95,105,110,115,116,97,108,108,243, + 5,0,0,115,8,0,0,0,0,2,8,1,6,1,20,1, + 114,40,1,0,0,41,1,114,0,0,0,0,41,2,114,1, + 0,0,0,114,2,0,0,0,41,1,114,49,0,0,0,41, + 1,78,41,3,78,78,78,41,2,114,62,0,0,0,114,62, + 0,0,0,41,1,84,41,1,78,41,1,78,41,61,114,111, + 0,0,0,114,12,0,0,0,90,37,95,67,65,83,69,95, + 73,78,83,69,78,83,73,84,73,86,69,95,80,76,65,84, + 70,79,82,77,83,95,66,89,84,69,83,95,75,69,89,114, + 11,0,0,0,114,13,0,0,0,114,19,0,0,0,114,21, + 0,0,0,114,30,0,0,0,114,40,0,0,0,114,41,0, + 0,0,114,45,0,0,0,114,46,0,0,0,114,48,0,0, + 0,114,58,0,0,0,218,4,116,121,112,101,218,8,95,95, + 99,111,100,101,95,95,114,144,0,0,0,114,17,0,0,0, + 114,131,0,0,0,114,16,0,0,0,114,20,0,0,0,114, + 211,0,0,0,114,77,0,0,0,114,76,0,0,0,114,88, + 0,0,0,114,78,0,0,0,90,23,68,69,66,85,71,95, + 66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,69, + 83,90,27,79,80,84,73,77,73,90,69,68,95,66,89,84, + 69,67,79,68,69,95,83,85,70,70,73,88,69,83,114,83, + 0,0,0,114,89,0,0,0,114,95,0,0,0,114,99,0, + 0,0,114,101,0,0,0,114,120,0,0,0,114,127,0,0, + 0,114,135,0,0,0,114,139,0,0,0,114,141,0,0,0, + 114,147,0,0,0,114,152,0,0,0,114,154,0,0,0,114, + 159,0,0,0,218,6,111,98,106,101,99,116,114,166,0,0, + 0,114,171,0,0,0,114,172,0,0,0,114,187,0,0,0, + 114,197,0,0,0,114,214,0,0,0,114,222,0,0,0,114, + 227,0,0,0,114,233,0,0,0,114,228,0,0,0,114,234, + 0,0,0,114,253,0,0,0,114,255,0,0,0,114,13,1, + 0,0,114,31,1,0,0,114,165,0,0,0,114,38,1,0, + 0,114,40,1,0,0,114,4,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,6,0,0,0,218,8,60,109,111,100, + 117,108,101,62,24,0,0,0,115,116,0,0,0,4,0,4, + 1,4,1,2,1,6,3,8,17,8,5,8,5,8,6,8, + 12,8,10,8,9,8,5,8,7,10,22,10,126,16,1,12, + 2,4,1,4,2,6,2,6,2,8,2,16,45,8,34,8, + 19,8,12,8,12,8,28,8,17,8,33,8,28,8,24,10, + 13,10,10,10,11,8,14,6,3,4,1,14,67,14,64,14, + 29,16,127,0,17,14,41,18,45,18,26,4,3,18,53,14, + 60,14,42,14,127,0,5,14,127,0,22,10,23,8,11,8, + 64, }; diff --git a/Python/pyhash.c b/Python/pyhash.c index aa49eeb35bb..bc6786c7b8b 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -284,7 +284,6 @@ static PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * SIZEOF_PY_HASH_T, #endif /* Py_HASH_ALGORITHM == Py_HASH_FNV */ -#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH24 /* ************************************************************************** Copyright (c) 2013 Marek Majkowski @@ -364,10 +363,10 @@ static PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * SIZEOF_PY_HASH_T, HALF_ROUND(v2,v1,v0,v3,17,21); -static Py_hash_t -siphash24(const void *src, Py_ssize_t src_sz) { - uint64_t k0 = _le64toh(_Py_HashSecret.siphash.k0); - uint64_t k1 = _le64toh(_Py_HashSecret.siphash.k1); +static uint64_t +siphash24(uint64_t key0, uint64_t key1, const void *src, Py_ssize_t src_sz) { + uint64_t k0 = _le64toh(key0); + uint64_t k1 = _le64toh(key1); uint64_t b = (uint64_t)src_sz << 56; const uint64_t *in = (uint64_t*)src; @@ -412,12 +411,26 @@ siphash24(const void *src, Py_ssize_t src_sz) { /* modified */ t = (v0 ^ v1) ^ (v2 ^ v3); - return (Py_hash_t)t; + return t; +} + +static Py_hash_t +pysiphash(const void *src, Py_ssize_t src_sz) { + return (Py_hash_t)siphash24( + _Py_HashSecret.siphash.k0, _Py_HashSecret.siphash.k1, + src, src_sz); +} + +uint64_t +_Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz) +{ + return siphash24(key, 0, src, src_sz); } -static PyHash_FuncDef PyHash_Func = {siphash24, "siphash24", 64, 128}; -#endif /* Py_HASH_ALGORITHM == Py_HASH_SIPHASH24 */ +#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH24 +static PyHash_FuncDef PyHash_Func = {pysiphash, "siphash24", 64, 128}; +#endif #ifdef __cplusplus } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index b5285754ab0..26f74c80d03 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1053,7 +1053,8 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals, "Bad magic number in .pyc file"); return NULL; } - /* Skip mtime and size */ + /* Skip the rest of the header. */ + (void) PyMarshal_ReadLongFromFile(fp); (void) PyMarshal_ReadLongFromFile(fp); (void) PyMarshal_ReadLongFromFile(fp); if (PyErr_Occurred()) From webhook-mailer at python.org Sat Dec 9 14:24:21 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 09 Dec 2017 19:24:21 -0000 Subject: [Python-checkins] bpo-32260: don't byte swap siphash keys (#4771) Message-ID: https://github.com/python/cpython/commit/4e3e156391e70cd23cae18f2629ec323b3b1e7de commit: 4e3e156391e70cd23cae18f2629ec323b3b1e7de branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-09T11:24:18-08:00 summary: bpo-32260: don't byte swap siphash keys (#4771) Reference siphash takes the keys as a bytes, so it makes sense to byte swap when reifying the keys as 64-bit integers. However, Python's siphash takes host integers in to start with. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-09-11-03-51.bpo-32260.1DAO-p.rst M Python/pyhash.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-09-11-03-51.bpo-32260.1DAO-p.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-09-11-03-51.bpo-32260.1DAO-p.rst new file mode 100644 index 00000000000..523ffe0a611 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-09-11-03-51.bpo-32260.1DAO-p.rst @@ -0,0 +1,3 @@ +Don't byte swap the input keys to the SipHash algorithm on big-endian +platforms. This should ensure siphash gives consistent results across +platforms. diff --git a/Python/pyhash.c b/Python/pyhash.c index bc6786c7b8b..4494a2f6ef6 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -364,9 +364,7 @@ static PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * SIZEOF_PY_HASH_T, static uint64_t -siphash24(uint64_t key0, uint64_t key1, const void *src, Py_ssize_t src_sz) { - uint64_t k0 = _le64toh(key0); - uint64_t k1 = _le64toh(key1); +siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t b = (uint64_t)src_sz << 56; const uint64_t *in = (uint64_t*)src; From webhook-mailer at python.org Sat Dec 9 15:19:00 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 09 Dec 2017 20:19:00 -0000 Subject: [Python-checkins] fix my byte-swapping implementation (#4772) Message-ID: https://github.com/python/cpython/commit/83620773eef7380178ba84217a26fe22d1636474 commit: 83620773eef7380178ba84217a26fe22d1636474 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-09T12:18:56-08:00 summary: fix my byte-swapping implementation (#4772) files: M Python/import.c diff --git a/Python/import.c b/Python/import.c index b2d751111bf..892f3d1c6e4 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2197,21 +2197,21 @@ static PyObject * _imp_source_hash_impl(PyObject *module, long key, Py_buffer *source) /*[clinic end generated code: output=edb292448cf399ea input=9aaad1e590089789]*/ { - uint64_t hash = _Py_KeyedHash((uint64_t)key, source->buf, source->len); + union { + uint64_t x; + char data[sizeof(uint64_t)]; + } hash; + hash.x = _Py_KeyedHash((uint64_t)key, source->buf, source->len); #if !PY_LITTLE_ENDIAN // Force to little-endian. There really ought to be a succinct standard way // to do this. - union { - uint64_t x; - unsigned char data[sizeof(uint64_t)]; - } pun; - pun.x = hash; - for (size_t i = 0; i < sizeof(pun.data); i++) { - pun.data[sizeof(pun.data) - i - 1] = pun.data[i]; + for (size_t i = 0; i < sizeof(hash.data)/2; i++) { + char tmp = hash.data[i]; + hash.data[i] = hash.data[sizeof(hash.data) - i - 1]; + hash.data[sizeof(hash.data) - i - 1] = tmp; } - hash = pun.x; #endif - return PyBytes_FromStringAndSize((const char *)&hash, sizeof(hash)); + return PyBytes_FromStringAndSize(hash.data, sizeof(hash.data)); } From webhook-mailer at python.org Sat Dec 9 16:11:42 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 09 Dec 2017 21:11:42 -0000 Subject: [Python-checkins] byte swap the raw hash secrets (more bpo-32260) (#4773) Message-ID: https://github.com/python/cpython/commit/60ed1308304964e5648d8bfc9b74bd549570fa83 commit: 60ed1308304964e5648d8bfc9b74bd549570fa83 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-09T13:11:39-08:00 summary: byte swap the raw hash secrets (more bpo-32260) (#4773) files: M Python/pyhash.c diff --git a/Python/pyhash.c b/Python/pyhash.c index 4494a2f6ef6..1537a0fb490 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -415,7 +415,7 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { static Py_hash_t pysiphash(const void *src, Py_ssize_t src_sz) { return (Py_hash_t)siphash24( - _Py_HashSecret.siphash.k0, _Py_HashSecret.siphash.k1, + _le64toh(_Py_HashSecret.siphash.k0), _le64toh(_Py_HashSecret.siphash.k1), src, src_sz); } From webhook-mailer at python.org Sat Dec 9 19:14:25 2017 From: webhook-mailer at python.org (Nick Coghlan) Date: Sun, 10 Dec 2017 00:14:25 -0000 Subject: [Python-checkins] bpo-31506: Improve the error message logic for class instantiation (GH-4740) Message-ID: https://github.com/python/cpython/commit/780acc89bccf9999332d334a27887684cc942eb6 commit: 780acc89bccf9999332d334a27887684cc942eb6 branch: master author: Sanyam Khurana <8039608+CuriousLearner at users.noreply.github.com> committer: Nick Coghlan date: 2017-12-10T10:14:22+10:00 summary: bpo-31506: Improve the error message logic for class instantiation (GH-4740) The error messages in `object.__new__` and `object.__init__` now aim to point the user more directly at the name of the class being instantiated in cases where they *haven't* been overridden (on the assumption that the actual problem is a missing `__new__` or `__init__` definition in the class body). When they *have* been overridden, the errors still report themselves as coming from object, on the assumption that the problem is with the call up to the base class in the method implementation, rather than with the way the constructor is being called. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst M Lib/test/test_class.py M Objects/typeobject.c diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index ecc01f27795..a916e878b7a 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -595,5 +595,54 @@ class A: with self.assertRaises(TypeError): type.__setattr__(A, b'x', None) + def testConstructorErrorMessages(self): + # bpo-31506: Improves the error message logic for object_new & object_init + + # Class without any method overrides + class C: + pass + + with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): + C(42) + + with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): + C.__new__(C, 42) + + with self.assertRaisesRegex(TypeError, r'C\(\).__init__\(\) takes no arguments'): + C().__init__(42) + + with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): + object.__new__(C, 42) + + with self.assertRaisesRegex(TypeError, r'C\(\).__init__\(\) takes no arguments'): + object.__init__(C(), 42) + + # Class with both `__init__` & `__new__` method overriden + class D: + def __new__(cls, *args, **kwargs): + super().__new__(cls, *args, **kwargs) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + D(42) + + with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + D.__new__(D, 42) + + with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'): + object.__new__(D, 42) + + # Class that only overrides __init__ + class E: + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'): + E().__init__(42) + + with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'): + object.__init__(E(), 42) + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst new file mode 100644 index 00000000000..ceb9ee2ce8a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-07-23-44-29.bpo-31506.j1U2fU.rst @@ -0,0 +1,2 @@ +Improve the error message logic for object.__new__ and object.__init__. +Patch by Sanyam Khurana. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2a8118b43c5..73f94e76c90 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3592,11 +3592,11 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds) PyTypeObject *type = Py_TYPE(self); if (excess_args(args, kwds)) { if (type->tp_init != object_init) { - PyErr_SetString(PyExc_TypeError, "object() takes no arguments"); + PyErr_SetString(PyExc_TypeError, "object.__init__() takes no arguments"); return -1; } if (type->tp_new == object_new) { - PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments", + PyErr_Format(PyExc_TypeError, "%.200s().__init__() takes no arguments", type->tp_name); return -1; } @@ -3609,7 +3609,7 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { if (excess_args(args, kwds)) { if (type->tp_new != object_new) { - PyErr_SetString(PyExc_TypeError, "object() takes no arguments"); + PyErr_SetString(PyExc_TypeError, "object.__new__() takes no arguments"); return NULL; } if (type->tp_init == object_init) { From webhook-mailer at python.org Sun Dec 10 01:10:05 2017 From: webhook-mailer at python.org (INADA Naoki) Date: Sun, 10 Dec 2017 06:10:05 -0000 Subject: [Python-checkins] bpo-30806: Fix netrc.__repr__() format (GH-2491) Message-ID: https://github.com/python/cpython/commit/3b9173d33adc2903e1af461214333b0052d7b1e9 commit: 3b9173d33adc2903e1af461214333b0052d7b1e9 branch: 2.7 author: Steven Loria committer: INADA Naoki date: 2017-12-10T15:09:58+09:00 summary: bpo-30806: Fix netrc.__repr__() format (GH-2491) netrc file format doesn't support quotes and escapes. See https://linux.die.net/man/5/netrc files: A Misc/NEWS.d/next/Library/2017-09-29.bpo-30806.lP5GrH.rst M Lib/netrc.py M Lib/test/test_netrc.py diff --git a/Lib/netrc.py b/Lib/netrc.py index 4b18973d51e..16bc347023a 100644 --- a/Lib/netrc.py +++ b/Lib/netrc.py @@ -130,15 +130,15 @@ def __repr__(self): rep = "" for host in self.hosts.keys(): attrs = self.hosts[host] - rep = rep + "machine "+ host + "\n\tlogin " + repr(attrs[0]) + "\n" + rep += "machine {host}\n\tlogin {attrs[0]}\n".format(host=host, attrs=attrs) if attrs[1]: - rep = rep + "account " + repr(attrs[1]) - rep = rep + "\tpassword " + repr(attrs[2]) + "\n" + rep += "\taccount {attrs[1]}\n".format(attrs=attrs) + rep += "\tpassword {attrs[2]}\n".format(attrs=attrs) for macro in self.macros.keys(): - rep = rep + "macdef " + macro + "\n" + rep += "macdef {macro}\n".format(macro=macro) for line in self.macros[macro]: - rep = rep + line - rep = rep + "\n" + rep += line + rep += "\n" return rep if __name__ == '__main__': diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py index 4156c535eff..4d49a55cb64 100644 --- a/Lib/test/test_netrc.py +++ b/Lib/test/test_netrc.py @@ -5,25 +5,29 @@ class NetrcTestCase(unittest.TestCase): - def make_nrc(self, test_data): + def make_nrc(self, test_data, cleanup=True): test_data = textwrap.dedent(test_data) mode = 'w' if sys.platform != 'cygwin': mode += 't' with open(temp_filename, mode) as fp: fp.write(test_data) - self.addCleanup(os.unlink, temp_filename) + if cleanup: + self.addCleanup(os.unlink, temp_filename) return netrc.netrc(temp_filename) def test_default(self): nrc = self.make_nrc("""\ machine host1.domain.com login log1 password pass1 account acct1 default login log2 password pass2 - """) + """, cleanup=False) self.assertEqual(nrc.hosts['host1.domain.com'], ('log1', 'acct1', 'pass1')) self.assertEqual(nrc.hosts['default'], ('log2', None, 'pass2')) + nrc2 = self.make_nrc(nrc.__repr__(), cleanup=True) + self.assertEqual(nrc.hosts, nrc2.hosts) + def test_macros(self): nrc = self.make_nrc("""\ macdef macro1 diff --git a/Misc/NEWS.d/next/Library/2017-09-29.bpo-30806.lP5GrH.rst b/Misc/NEWS.d/next/Library/2017-09-29.bpo-30806.lP5GrH.rst new file mode 100644 index 00000000000..afad1b2fb26 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-29.bpo-30806.lP5GrH.rst @@ -0,0 +1 @@ +Fix the string representation of a netrc object. From webhook-mailer at python.org Sun Dec 10 04:02:56 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 10 Dec 2017 09:02:56 -0000 Subject: [Python-checkins] Removed doubled 'bpo-'. (#4777) Message-ID: https://github.com/python/cpython/commit/f658641a05651e0eb717bb40e2c85dca3470369d commit: f658641a05651e0eb717bb40e2c85dca3470369d branch: master author: Terry Jan Reedy committer: GitHub date: 2017-12-10T04:02:53-05:00 summary: Removed doubled 'bpo-'. (#4777) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index be68adf6670..9784c46b1c5 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -84,7 +84,7 @@ bpo-31421: Document how IDLE runs tkinter programs. IDLE calls tcl/tk update in the background in order to make live interaction and experimentatin with tkinter applications much easier. -bpo-bpo-31414: Fix tk entry box tests by deleting first. +bpo-31414: Fix tk entry box tests by deleting first. Adding to an int entry is not the same as deleting and inserting because int('') will fail. Patch by Terry Jan Reedy. From solipsis at pitrou.net Sun Dec 10 04:11:31 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 10 Dec 2017 09:11:31 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=8 Message-ID: <20171210091131.94804.2AFBCFB3209B74BF@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [1, -2, 2] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogYa1opz', '--timeout', '7200'] From webhook-mailer at python.org Sun Dec 10 05:38:41 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 10 Dec 2017 10:38:41 -0000 Subject: [Python-checkins] Removed doubled 'bpo-'. (GH-4777) (#4780) Message-ID: https://github.com/python/cpython/commit/f446b244154e21d0904dfd20243f6416e0cdc9ea commit: f446b244154e21d0904dfd20243f6416e0cdc9ea branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2017-12-10T05:38:38-05:00 summary: Removed doubled 'bpo-'. (GH-4777) (#4780) (cherry picked from commit f658641a05651e0eb717bb40e2c85dca3470369d) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 56d37f3baa4..5b9d2abaca0 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -84,7 +84,7 @@ bpo-31421: Document how IDLE runs tkinter programs. IDLE calls tcl/tk update in the background in order to make live interaction and experimentatin with tkinter applications much easier. -bpo-bpo-31414: Fix tk entry box tests by deleting first. +bpo-31414: Fix tk entry box tests by deleting first. Adding to an int entry is not the same as deleting and inserting because int('') will fail. Patch by Terry Jan Reedy. From webhook-mailer at python.org Sun Dec 10 12:35:02 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sun, 10 Dec 2017 17:35:02 -0000 Subject: [Python-checkins] bpo-32114: Updated the documentation for get_event_loop to reflect the policy change (#4510) Message-ID: https://github.com/python/cpython/commit/77106b2c21e59d0466742cc3afa50f9e8345e186 commit: 77106b2c21e59d0466742cc3afa50f9e8345e186 branch: master author: Pablo Galindo committer: Yury Selivanov date: 2017-12-10T12:34:59-05:00 summary: bpo-32114: Updated the documentation for get_event_loop to reflect the policy change (#4510) files: M Doc/library/asyncio-eventloops.rst diff --git a/Doc/library/asyncio-eventloops.rst b/Doc/library/asyncio-eventloops.rst index 7970e9039df..2097260e219 100644 --- a/Doc/library/asyncio-eventloops.rst +++ b/Doc/library/asyncio-eventloops.rst @@ -189,10 +189,15 @@ An event loop policy must implement the following interface: The default policy defines context as the current thread, and manages an event -loop per thread that interacts with :mod:`asyncio`. If the current thread -doesn't already have an event loop associated with it, the default policy's -:meth:`~AbstractEventLoopPolicy.get_event_loop` method creates one when -called from the main thread, but raises :exc:`RuntimeError` otherwise. +loop per thread that interacts with :mod:`asyncio`. An exception to this rule +happens when :meth:`~AbstractEventLoopPolicy.get_event_loop` is called from a +running future/coroutine, in which case it will return the current loop +running that future/coroutine. + +If the current thread doesn't already have an event loop associated with it, +the default policy's :meth:`~AbstractEventLoopPolicy.get_event_loop` method +creates one when called from the main thread, but raises :exc:`RuntimeError` +otherwise. Access to the global loop policy From webhook-mailer at python.org Sun Dec 10 12:40:21 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sun, 10 Dec 2017 17:40:21 -0000 Subject: [Python-checkins] Skip test_read_pty_output test on macOS for poll and select. (#4774) Message-ID: https://github.com/python/cpython/commit/c4d9df5fd719ad08e68e0950ce22a80f43e4f35d commit: c4d9df5fd719ad08e68e0950ce22a80f43e4f35d branch: master author: Yury Selivanov committer: GitHub date: 2017-12-10T12:40:19-05:00 summary: Skip test_read_pty_output test on macOS for poll and select. (#4774) Starting with 10.13.2 the test hangs forever. files: M Lib/test/test_asyncio/test_events.py diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 2e8f46dd41e..01300246fda 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1486,9 +1486,7 @@ def test_unclosed_pipe_transport(self): @unittest.skipUnless(sys.platform != 'win32', "Don't support pipes for Windows") - # select, poll and kqueue don't support character devices (PTY) on Mac OS X - # older than 10.6 (Snow Leopard) - @support.requires_mac_ver(10, 6) + @unittest.skipIf(sys.platform == 'darwin', 'test hangs on MacOS') # Issue #20495: The test hangs on FreeBSD 7.2 but pass on FreeBSD 9 @support.requires_freebsd_version(8) def test_read_pty_output(self): From webhook-mailer at python.org Sun Dec 10 18:36:15 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sun, 10 Dec 2017 23:36:15 -0000 Subject: [Python-checkins] bpo-32262: Fix codestyle; use f-strings formatting where necessary. (#4775) Message-ID: https://github.com/python/cpython/commit/6370f345e1d5829e1fba59cd695c8b82c5a8c620 commit: 6370f345e1d5829e1fba59cd695c8b82c5a8c620 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-10T18:36:12-05:00 summary: bpo-32262: Fix codestyle; use f-strings formatting where necessary. (#4775) files: M Lib/asyncio/__init__.py M Lib/asyncio/base_events.py M Lib/asyncio/base_futures.py M Lib/asyncio/base_subprocess.py M Lib/asyncio/base_tasks.py M Lib/asyncio/constants.py M Lib/asyncio/coroutines.py M Lib/asyncio/events.py M Lib/asyncio/futures.py M Lib/asyncio/locks.py M Lib/asyncio/proactor_events.py M Lib/asyncio/protocols.py M Lib/asyncio/queues.py M Lib/asyncio/selector_events.py M Lib/asyncio/sslproto.py M Lib/asyncio/streams.py M Lib/asyncio/subprocess.py M Lib/asyncio/tasks.py M Lib/asyncio/transports.py M Lib/asyncio/unix_events.py M Lib/asyncio/windows_events.py M Lib/asyncio/windows_utils.py M Lib/test/test_asyncio/test_locks.py M Lib/test/test_asyncio/test_streams.py diff --git a/Lib/asyncio/__init__.py b/Lib/asyncio/__init__.py index 1ee1b2516d4..dd6686de840 100644 --- a/Lib/asyncio/__init__.py +++ b/Lib/asyncio/__init__.py @@ -1,5 +1,7 @@ """The asyncio package, tracking PEP 3156.""" +# flake8: noqa + import sys # This relies on each of the submodules having an __all__ variable. diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index ab92a0b5807..5cc7944f24a 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -36,7 +36,7 @@ from .log import logger -__all__ = ['BaseEventLoop'] +__all__ = 'BaseEventLoop', # Minimum number of _scheduled timer handles before cleanup of @@ -173,8 +173,7 @@ def _ensure_resolved(address, *, family=0, type=socket.SOCK_STREAM, proto=0, def _run_until_complete_cb(fut): exc = fut._exception - if (isinstance(exc, BaseException) - and not isinstance(exc, Exception)): + if isinstance(exc, BaseException) and not isinstance(exc, Exception): # Issue #22429: run_forever() already finished, no need to # stop it. return @@ -190,7 +189,7 @@ def __init__(self, loop, sockets): self._waiters = [] def __repr__(self): - return '<%s sockets=%r>' % (self.__class__.__name__, self.sockets) + return f'<{self.__class__.__name__} sockets={self.sockets!r}>' def _attach(self): assert self.sockets is not None @@ -262,9 +261,10 @@ def __init__(self): self._asyncgens_shutdown_called = False def __repr__(self): - return ('<%s running=%s closed=%s debug=%s>' - % (self.__class__.__name__, self.is_running(), - self.is_closed(), self.get_debug())) + return ( + f'<{self.__class__.__name__} running={self.is_running()} ' + f'closed={self.is_closed()} debug={self.get_debug()}>' + ) def create_future(self): """Create a Future object attached to the loop.""" @@ -362,8 +362,8 @@ def _asyncgen_finalizer_hook(self, agen): def _asyncgen_firstiter_hook(self, agen): if self._asyncgens_shutdown_called: warnings.warn( - "asynchronous generator {!r} was scheduled after " - "loop.shutdown_asyncgens() call".format(agen), + f"asynchronous generator {agen!r} was scheduled after " + f"loop.shutdown_asyncgens() call", ResourceWarning, source=self) self._asyncgens.add(agen) @@ -388,8 +388,8 @@ def _asyncgen_firstiter_hook(self, agen): for result, agen in zip(results, closing_agens): if isinstance(result, Exception): self.call_exception_handler({ - 'message': 'an error occurred during closing of ' - 'asynchronous generator {!r}'.format(agen), + 'message': f'an error occurred during closing of ' + f'asynchronous generator {agen!r}', 'exception': result, 'asyncgen': agen }) @@ -495,7 +495,7 @@ def is_closed(self): def __del__(self): if not self.is_closed(): - warnings.warn("unclosed event loop %r" % self, ResourceWarning, + warnings.warn(f"unclosed event loop {self!r}", ResourceWarning, source=self) if not self.is_running(): self.close() @@ -573,12 +573,11 @@ def _check_callback(self, callback, method): if (coroutines.iscoroutine(callback) or coroutines.iscoroutinefunction(callback)): raise TypeError( - "coroutines cannot be used with {}()".format(method)) + f"coroutines cannot be used with {method}()") if not callable(callback): raise TypeError( - 'a callable object was expected by {}(), got {!r}'.format( - method, callback)) - + f'a callable object was expected by {method}(), ' + f'got {callback!r}') def _call_soon(self, callback, args): handle = events.Handle(callback, args, self) @@ -630,15 +629,15 @@ def set_default_executor(self, executor): self._default_executor = executor def _getaddrinfo_debug(self, host, port, family, type, proto, flags): - msg = ["%s:%r" % (host, port)] + msg = [f"{host}:{port!r}"] if family: - msg.append('family=%r' % family) + msg.append(f'family={family!r}' % family) if type: - msg.append('type=%r' % type) + msg.append(f'type={type!r}') if proto: - msg.append('proto=%r' % proto) + msg.append(f'proto={proto!r}') if flags: - msg.append('flags=%r' % flags) + msg.append(f'flags={flags!r}') msg = ', '.join(msg) logger.debug('Get address info %s', msg) @@ -646,8 +645,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): addrinfo = socket.getaddrinfo(host, port, family, type, proto, flags) dt = self.time() - t0 - msg = ('Getting address info %s took %.3f ms: %r' - % (msg, dt * 1e3, addrinfo)) + msg = f'Getting address info {msg} took {dt * 1e3:.3f}ms: {addrinfo!r}' if dt >= self.slow_callback_duration: logger.info(msg) else: @@ -738,11 +736,12 @@ def getnameinfo(self, sockaddr, flags=0): sock.bind(laddr) break except OSError as exc: - exc = OSError( - exc.errno, 'error while ' - 'attempting to bind on address ' - '{!r}: {}'.format( - laddr, exc.strerror.lower())) + msg = ( + f'error while attempting to bind on ' + f'address {laddr!r}: ' + f'{exc.strerror.lower()}' + ) + exc = OSError(exc.errno, msg) exceptions.append(exc) else: sock.close() @@ -786,7 +785,7 @@ def getnameinfo(self, sockaddr, flags=0): # Disallowing AF_UNIX in this method, breaks backwards # compatibility. raise ValueError( - 'A Stream Socket was expected, got {!r}'.format(sock)) + f'A Stream Socket was expected, got {sock!r}') transport, protocol = await self._create_connection_transport( sock, protocol_factory, ssl, server_hostname) @@ -830,7 +829,7 @@ def getnameinfo(self, sockaddr, flags=0): if sock is not None: if not _is_dgram_socket(sock): raise ValueError( - 'A UDP Socket was expected, got {!r}'.format(sock)) + f'A UDP Socket was expected, got {sock!r}') if (local_addr or remote_addr or family or proto or flags or reuse_address or reuse_port or allow_broadcast): @@ -839,11 +838,10 @@ def getnameinfo(self, sockaddr, flags=0): family=family, proto=proto, flags=flags, reuse_address=reuse_address, reuse_port=reuse_port, allow_broadcast=allow_broadcast) - problems = ', '.join( - '{}={}'.format(k, v) for k, v in opts.items() if v) + problems = ', '.join(f'{k}={v}' for k, v in opts.items() if v) raise ValueError( - 'socket modifier keyword arguments can not be used ' - 'when sock is specified. ({})'.format(problems)) + f'socket modifier keyword arguments can not be used ' + f'when sock is specified. ({problems})') sock.setblocking(False) r_addr = None else: @@ -953,7 +951,7 @@ def getnameinfo(self, sockaddr, flags=0): type=socket.SOCK_STREAM, flags=flags, loop=self) if not infos: - raise OSError('getaddrinfo({!r}) returned empty list'.format(host)) + raise OSError(f'getaddrinfo({host!r}) returned empty list') return infos async def create_server(self, protocol_factory, host=None, port=None, @@ -967,8 +965,8 @@ def getnameinfo(self, sockaddr, flags=0): reuse_port=None): """Create a TCP server. - The host parameter can be a string, in that case the TCP server is bound - to host and port. + The host parameter can be a string, in that case the TCP server is + bound to host and port. The host parameter can also be a sequence of strings and in that case the TCP server is bound to all hosts of the sequence. If a host @@ -1046,8 +1044,7 @@ def getnameinfo(self, sockaddr, flags=0): if sock is None: raise ValueError('Neither host/port nor sock were specified') if not _is_stream_socket(sock): - raise ValueError( - 'A Stream Socket was expected, got {!r}'.format(sock)) + raise ValueError(f'A Stream Socket was expected, got {sock!r}') sockets = [sock] server = Server(self, sockets) @@ -1070,8 +1067,7 @@ def getnameinfo(self, sockaddr, flags=0): returns a (transport, protocol) pair. """ if not _is_stream_socket(sock): - raise ValueError( - 'A Stream Socket was expected, got {!r}'.format(sock)) + raise ValueError(f'A Stream Socket was expected, got {sock!r}') transport, protocol = await self._create_connection_transport( sock, protocol_factory, ssl, '', server_side=True) @@ -1117,14 +1113,14 @@ def getnameinfo(self, sockaddr, flags=0): def _log_subprocess(self, msg, stdin, stdout, stderr): info = [msg] if stdin is not None: - info.append('stdin=%s' % _format_pipe(stdin)) + info.append(f'stdin={_format_pipe(stdin)}') if stdout is not None and stderr == subprocess.STDOUT: - info.append('stdout=stderr=%s' % _format_pipe(stdout)) + info.append(f'stdout=stderr={_format_pipe(stdout)}') else: if stdout is not None: - info.append('stdout=%s' % _format_pipe(stdout)) + info.append(f'stdout={_format_pipe(stdout)}') if stderr is not None: - info.append('stderr=%s' % _format_pipe(stderr)) + info.append(f'stderr={_format_pipe(stderr)}') logger.debug(' '.join(info)) async def subprocess_shell(self, protocol_factory, cmd, *, @@ -1167,14 +1163,14 @@ def _log_subprocess(self, msg, stdin, stdout, stderr): popen_args = (program,) + args for arg in popen_args: if not isinstance(arg, (str, bytes)): - raise TypeError("program arguments must be " - "a bytes or text string, not %s" - % type(arg).__name__) + raise TypeError( + f"program arguments must be a bytes or text string, " + f"not {type(arg).__name__}") protocol = protocol_factory() if self._debug: # don't log parameters: they may contain sensitive information # (password) and may be too long - debug_log = 'execute program %r' % program + debug_log = f'execute program {program!r}' self._log_subprocess(debug_log, stdin, stdout, stderr) transport = await self._make_subprocess_transport( protocol, popen_args, False, stdin, stdout, stderr, @@ -1201,8 +1197,8 @@ def set_exception_handler(self, handler): documentation for details about context). """ if handler is not None and not callable(handler): - raise TypeError('A callable object or None is expected, ' - 'got {!r}'.format(handler)) + raise TypeError(f'A callable object or None is expected, ' + f'got {handler!r}') self._exception_handler = handler def default_exception_handler(self, context): @@ -1230,10 +1226,11 @@ def default_exception_handler(self, context): else: exc_info = False - if ('source_traceback' not in context - and self._current_handle is not None - and self._current_handle._source_traceback): - context['handle_traceback'] = self._current_handle._source_traceback + if ('source_traceback' not in context and + self._current_handle is not None and + self._current_handle._source_traceback): + context['handle_traceback'] = \ + self._current_handle._source_traceback log_lines = [message] for key in sorted(context): @@ -1250,7 +1247,7 @@ def default_exception_handler(self, context): value += tb.rstrip() else: value = repr(value) - log_lines.append('{}: {}'.format(key, value)) + log_lines.append(f'{key}: {value}') logger.error('\n'.join(log_lines), exc_info=exc_info) @@ -1438,18 +1435,19 @@ def _set_coroutine_wrapper(self, enabled): 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) + f"loop.set_debug(True): cannot set debug coroutine " + f"wrapper; another wrapper is already set " + f"{current_wrapper!r}", + 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) + f"loop.set_debug(False): cannot unset debug coroutine " + f"wrapper; another wrapper was set {current_wrapper!r}", + RuntimeWarning) else: set_wrapper(None) self._coroutine_wrapper_set = False diff --git a/Lib/asyncio/base_futures.py b/Lib/asyncio/base_futures.py index 01259a062e6..2ee82c3f057 100644 --- a/Lib/asyncio/base_futures.py +++ b/Lib/asyncio/base_futures.py @@ -1,4 +1,4 @@ -__all__ = [] +__all__ = () import concurrent.futures._base import reprlib @@ -48,7 +48,7 @@ def format_cb(callback): cb = '{}, <{} more>, {}'.format(format_cb(cb[0]), size - 2, format_cb(cb[-1])) - return 'cb=[%s]' % cb + return f'cb=[{cb}]' def _future_repr_info(future): @@ -57,15 +57,15 @@ def _future_repr_info(future): info = [future._state.lower()] if future._state == _FINISHED: if future._exception is not None: - info.append('exception={!r}'.format(future._exception)) + info.append(f'exception={future._exception!r}') else: # use reprlib to limit the length of the output, especially # for very long strings result = reprlib.repr(future._result) - info.append('result={}'.format(result)) + info.append(f'result={result}') if future._callbacks: info.append(_format_callbacks(future._callbacks)) if future._source_traceback: frame = future._source_traceback[-1] - info.append('created at %s:%s' % (frame[0], frame[1])) + info.append(f'created at {frame[0]}:{frame[1]}') return info diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 7e5a901845d..7c17066f8bb 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -57,9 +57,9 @@ def __repr__(self): if self._closed: info.append('closed') if self._pid is not None: - info.append('pid=%s' % self._pid) + info.append(f'pid={self.pid}') if self._returncode is not None: - info.append('returncode=%s' % self._returncode) + info.append(f'returncode={self._returncode}') elif self._pid is not None: info.append('running') else: @@ -67,19 +67,19 @@ def __repr__(self): stdin = self._pipes.get(0) if stdin is not None: - info.append('stdin=%s' % stdin.pipe) + info.append(f'stdin={stdin.pipe}') stdout = self._pipes.get(1) stderr = self._pipes.get(2) if stdout is not None and stderr is stdout: - info.append('stdout=stderr=%s' % stdout.pipe) + info.append(f'stdout=stderr={stdout.pipe}') else: if stdout is not None: - info.append('stdout=%s' % stdout.pipe) + info.append(f'stdout={stdout.pipe}') if stderr is not None: - info.append('stderr=%s' % stderr.pipe) + info.append(f'stderr={stderr.pipe}') - return '<%s>' % ' '.join(info) + return '<{}>'.format(' '.join(info)) def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs): raise NotImplementedError @@ -103,12 +103,13 @@ def close(self): continue proto.pipe.close() - if (self._proc is not None - # the child process finished? - and self._returncode is None - # the child process finished but the transport was not notified yet? - and self._proc.poll() is None - ): + if (self._proc is not None and + # has the child process finished? + self._returncode is None and + # the child process has finished, but the + # transport hasn't been notified yet? + self._proc.poll() is None): + if self._loop.get_debug(): logger.warning('Close running child process: kill %r', self) @@ -121,7 +122,7 @@ def close(self): def __del__(self): if not self._closed: - warnings.warn("unclosed transport %r" % self, ResourceWarning, + warnings.warn(f"unclosed transport {self!r}", ResourceWarning, source=self) self.close() @@ -206,8 +207,7 @@ def _process_exited(self, returncode): assert returncode is not None, returncode assert self._returncode is None, self._returncode if self._loop.get_debug(): - logger.info('%r exited with return code %r', - self, returncode) + logger.info('%r exited with return code %r', self, returncode) self._returncode = returncode if self._proc.returncode is None: # asyncio uses a child watcher: copy the status into the Popen @@ -263,8 +263,7 @@ def connection_made(self, transport): self.pipe = transport def __repr__(self): - return ('<%s fd=%s pipe=%r>' - % (self.__class__.__name__, self.fd, self.pipe)) + return f'<{self.__class__.__name__} fd={self.fd} pipe={self.pipe!r}>' def connection_lost(self, exc): self.disconnected = True diff --git a/Lib/asyncio/base_tasks.py b/Lib/asyncio/base_tasks.py index 5f34434c576..3ce51f6a986 100644 --- a/Lib/asyncio/base_tasks.py +++ b/Lib/asyncio/base_tasks.py @@ -13,10 +13,10 @@ def _task_repr_info(task): info[0] = 'cancelling' coro = coroutines._format_coroutine(task._coro) - info.insert(1, 'coro=<%s>' % coro) + info.insert(1, f'coro=<{coro}>') if task._fut_waiter is not None: - info.insert(2, 'wait_for=%r' % task._fut_waiter) + info.insert(2, f'wait_for={task._fut_waiter!r}') return info @@ -61,15 +61,15 @@ def _task_print_stack(task, limit, file): linecache.checkcache(filename) line = linecache.getline(filename, lineno, f.f_globals) extracted_list.append((filename, lineno, name, line)) + exc = task._exception if not extracted_list: - print('No stack for %r' % task, file=file) + print(f'No stack for {task!r}', file=file) elif exc is not None: - print('Traceback for %r (most recent call last):' % task, - file=file) + print(f'Traceback for {task!r} (most recent call last):', file=file) else: - print('Stack for %r (most recent call last):' % task, - file=file) + print(f'Stack for {task!r} (most recent call last):', file=file) + traceback.print_list(extracted_list, file=file) if exc is not None: for line in traceback.format_exception_only(exc.__class__, exc): diff --git a/Lib/asyncio/constants.py b/Lib/asyncio/constants.py index 60ca0da75f8..dfe97f49859 100644 --- a/Lib/asyncio/constants.py +++ b/Lib/asyncio/constants.py @@ -1,5 +1,3 @@ -"""Constants.""" - # After the connection is lost, log warnings after this many write()s. LOG_THRESHOLD_FOR_CONNLOST_WRITES = 5 diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index 7d2ca05d2a0..d7e6b4c1ccb 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -1,9 +1,7 @@ -__all__ = ['coroutine', - 'iscoroutinefunction', 'iscoroutine'] +__all__ = 'coroutine', 'iscoroutinefunction', 'iscoroutine' import functools import inspect -import opcode import os import sys import traceback @@ -27,9 +25,8 @@ def _is_debug_mode(): # before you define your coroutines. A downside of using this feature # is that tracebacks show entries for the CoroWrapper.__next__ method # when _DEBUG is true. - return (sys.flags.dev_mode - or (not sys.flags.ignore_environment - and bool(os.environ.get('PYTHONASYNCIODEBUG')))) + return sys.flags.dev_mode or (not sys.flags.ignore_environment and + bool(os.environ.get('PYTHONASYNCIODEBUG'))) _DEBUG = _is_debug_mode() @@ -58,8 +55,9 @@ def __repr__(self): coro_repr = _format_coroutine(self) if self._source_traceback: frame = self._source_traceback[-1] - coro_repr += ', created at %s:%s' % (frame[0], frame[1]) - return '<%s %s>' % (self.__class__.__name__, coro_repr) + coro_repr += f', created at {frame[0]}:{frame[1]}' + + return f'<{self.__class__.__name__} {coro_repr}>' def __iter__(self): return self @@ -92,8 +90,8 @@ def __await__(self): cr_await = getattr(self.gen, 'cr_await', None) if cr_await is not None: raise RuntimeError( - "Cannot await on coroutine {!r} while it's " - "awaiting for {!r}".format(self.gen, cr_await)) + f"Cannot await on coroutine {self.gen!r} while it's " + f"awaiting for {cr_await!r}") return self @property @@ -123,7 +121,7 @@ def __del__(self): if frame is None: frame = getattr(gen, 'cr_frame', None) if frame is not None and frame.f_lasti == -1: - msg = '%r was never yielded from' % self + msg = f'{self!r} was never yielded from' tb = getattr(self, '_source_traceback', ()) if tb: tb = ''.join(traceback.format_list(tb)) @@ -154,11 +152,10 @@ def coroutine(func): def coro(*args, **kw): res = func(*args, **kw) if (base_futures.isfuture(res) or inspect.isgenerator(res) or - isinstance(res, CoroWrapper)): + isinstance(res, CoroWrapper)): res = yield from res else: - # If 'func' returns an Awaitable (new in 3.5) we - # want to run it. + # If 'res' is an awaitable, run it. try: await_meth = res.__await__ except AttributeError: @@ -219,7 +216,7 @@ def _format_coroutine(coro): coro_name = getattr( coro, '__qualname__', getattr(coro, '__name__', type(coro).__name__)) - coro_name = '{}()'.format(coro_name) + coro_name = f'{coro_name}()' running = False try: @@ -231,7 +228,7 @@ def _format_coroutine(coro): pass if running: - return '{} running'.format(coro_name) + return f'{coro_name} running' else: return coro_name @@ -240,7 +237,7 @@ def _format_coroutine(coro): func = coro.func coro_name = coro.__qualname__ if coro_name is not None: - coro_name = '{}()'.format(coro_name) + coro_name = f'{coro_name}()' else: func = coro @@ -266,18 +263,14 @@ def _format_coroutine(coro): if source is not None: filename, lineno = source if coro_frame is None: - coro_repr = ('%s done, defined at %s:%s' - % (coro_name, filename, lineno)) + coro_repr = f'{coro_name} done, defined at {filename}:{lineno}' else: - coro_repr = ('%s running, defined at %s:%s' - % (coro_name, filename, lineno)) + coro_repr = f'{coro_name} running, defined at {filename}:{lineno}' elif coro_frame is not None: lineno = coro_frame.f_lineno - coro_repr = ('%s running at %s:%s' - % (coro_name, filename, lineno)) + coro_repr = f'{coro_name} running at {filename}:{lineno}' else: lineno = coro_code.co_firstlineno - coro_repr = ('%s done, defined at %s:%s' - % (coro_name, filename, lineno)) + coro_repr = f'{coro_name} done, defined at {filename}:{lineno}' return coro_repr diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 2cd6035973d..7db1ded8e8b 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -1,13 +1,14 @@ """Event loop and event loop policy.""" -__all__ = ['AbstractEventLoopPolicy', - 'AbstractEventLoop', 'AbstractServer', - 'Handle', 'TimerHandle', - 'get_event_loop_policy', 'set_event_loop_policy', - 'get_event_loop', 'set_event_loop', 'new_event_loop', - 'get_child_watcher', 'set_child_watcher', - '_set_running_loop', '_get_running_loop', - ] +__all__ = ( + 'AbstractEventLoopPolicy', + 'AbstractEventLoop', 'AbstractServer', + 'Handle', 'TimerHandle', + 'get_event_loop_policy', 'set_event_loop_policy', + 'get_event_loop', 'set_event_loop', 'new_event_loop', + 'get_child_watcher', 'set_child_watcher', + '_set_running_loop', '_get_running_loop', +) import functools import inspect @@ -44,9 +45,8 @@ def _format_args_and_kwargs(args, kwargs): if args: items.extend(reprlib.repr(arg) for arg in args) if kwargs: - items.extend('{}={}'.format(k, reprlib.repr(v)) - for k, v in kwargs.items()) - return '(' + ', '.join(items) + ')' + items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items()) + return '({})'.format(', '.join(items)) def _format_callback(func, args, kwargs, suffix=''): @@ -66,11 +66,12 @@ def _format_callback(func, args, kwargs, suffix=''): func_repr += suffix return func_repr + def _format_callback_source(func, args): func_repr = _format_callback(func, args, None) source = _get_function_source(func) if source: - func_repr += ' at %s:%s' % source + func_repr += f' at {source[0]}:{source[1]}' return func_repr @@ -116,14 +117,14 @@ def _repr_info(self): 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])) + info.append(f'created at {frame[0]}:{frame[1]}') return info def __repr__(self): if self._repr is not None: return self._repr info = self._repr_info() - return '<%s>' % ' '.join(info) + return '<{}>'.format(' '.join(info)) def cancel(self): if not self._cancelled: @@ -144,7 +145,7 @@ def _run(self): self._callback(*self._args) except Exception as exc: cb = _format_callback_source(self._callback, self._args) - msg = 'Exception in callback {}'.format(cb) + msg = f'Exception in callback {cb}' context = { 'message': msg, 'exception': exc, @@ -172,7 +173,7 @@ def __init__(self, when, callback, args, loop): def _repr_info(self): info = super()._repr_info() pos = 2 if self._cancelled else 1 - info.insert(pos, 'when=%s' % self._when) + info.insert(pos, f'when={self._when}') return info def __hash__(self): @@ -334,8 +335,8 @@ def set_default_executor(self, executor): If host is an empty string or None all interfaces are assumed and a list of multiple sockets will be returned (most likely - one for IPv4 and another one for IPv6). The host parameter can also be a - sequence (e.g. list) of hosts to bind to. + one for IPv4 and another one for IPv6). The host parameter can also be + a sequence (e.g. list) of hosts to bind to. family can be set to either AF_INET or AF_INET6 to force the socket to use IPv4 or IPv6. If not set it will be determined @@ -602,12 +603,14 @@ def get_event_loop(self): This may be None or an instance of EventLoop. """ if (self._local._loop is None and - not self._local._set_called and - isinstance(threading.current_thread(), threading._MainThread)): + not self._local._set_called and + isinstance(threading.current_thread(), threading._MainThread)): self.set_event_loop(self.new_event_loop()) + if self._local._loop is None: raise RuntimeError('There is no current event loop in thread %r.' % threading.current_thread().name) + return self._local._loop def set_event_loop(self, loop): diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 7b6204a626f..b805f99896d 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -1,12 +1,13 @@ """A Future class similar to the one in PEP 3148.""" -__all__ = ['CancelledError', 'TimeoutError', 'InvalidStateError', - 'Future', 'wrap_future', 'isfuture'] +__all__ = ( + 'CancelledError', 'TimeoutError', 'InvalidStateError', + 'Future', 'wrap_future', 'isfuture', +) import concurrent.futures import logging import sys -import traceback from . import base_futures from . import events @@ -82,7 +83,8 @@ def __init__(self, *, loop=None): _repr_info = base_futures._future_repr_info def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, ' '.join(self._repr_info())) + return '<{} {}>'.format(self.__class__.__name__, + ' '.join(self._repr_info())) def __del__(self): if not self._log_traceback: @@ -91,8 +93,8 @@ def __del__(self): return exc = self._exception context = { - 'message': ('%s exception was never retrieved' - % self.__class__.__name__), + 'message': + f'{self.__class__.__name__} exception was never retrieved', 'exception': exc, 'future': self, } @@ -237,7 +239,7 @@ def __iter__(self): assert self.done(), "yield from wasn't used with future" return self.result() # May raise too. - __await__ = __iter__ # make compatible with 'await' expression + __await__ = __iter__ # make compatible with 'await' expression # Needed for testing purposes. @@ -330,7 +332,7 @@ def wrap_future(future, *, loop=None): if isfuture(future): return future assert isinstance(future, concurrent.futures.Future), \ - 'concurrent.futures.Future is expected, got {!r}'.format(future) + f'concurrent.futures.Future is expected, got {future!r}' if loop is None: loop = events.get_event_loop() new_future = loop.create_future() diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 57eb69e7cf0..54f62585983 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -1,6 +1,6 @@ """Synchronization primitives.""" -__all__ = ['Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore'] +__all__ = ('Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore') import collections import warnings @@ -157,8 +157,8 @@ def __repr__(self): res = super().__repr__() extra = 'locked' if self._locked else 'unlocked' if self._waiters: - extra = '{},waiters:{}'.format(extra, len(self._waiters)) - return '<{} [{}]>'.format(res[1:-1], extra) + extra = f'{extra}, waiters:{len(self._waiters)}' + return f'<{res[1:-1]} [{extra}]>' def locked(self): """Return True if lock is acquired.""" @@ -233,8 +233,8 @@ def __repr__(self): res = super().__repr__() extra = 'set' if self._value else 'unset' if self._waiters: - extra = '{},waiters:{}'.format(extra, len(self._waiters)) - return '<{} [{}]>'.format(res[1:-1], extra) + extra = f'{extra}, waiters:{len(self._waiters)}' + return f'<{res[1:-1]} [{extra}]>' def is_set(self): """Return True if and only if the internal flag is true.""" @@ -310,8 +310,8 @@ def __repr__(self): res = super().__repr__() extra = 'locked' if self.locked() else 'unlocked' if self._waiters: - extra = '{},waiters:{}'.format(extra, len(self._waiters)) - return '<{} [{}]>'.format(res[1:-1], extra) + extra = f'{extra}, waiters:{len(self._waiters)}' + return f'<{res[1:-1]} [{extra}]>' async def wait(self): """Wait until notified. @@ -419,11 +419,10 @@ def __init__(self, value=1, *, loop=None): def __repr__(self): res = super().__repr__() - extra = 'locked' if self.locked() else 'unlocked,value:{}'.format( - self._value) + extra = 'locked' if self.locked() else f'unlocked, value:{self._value}' if self._waiters: - extra = '{},waiters:{}'.format(extra, len(self._waiters)) - return '<{} [{}]>'.format(res[1:-1], extra) + extra = f'{extra}, waiters:{len(self._waiters)}' + return f'<{res[1:-1]} [{extra}]>' def _wake_up_next(self): while self._waiters: diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index d7aa5ff3017..3d48a2c05a2 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -4,7 +4,7 @@ proactor is only implemented on Windows with IOCP. """ -__all__ = ['BaseProactorEventLoop'] +__all__ = 'BaseProactorEventLoop', import socket import warnings @@ -50,17 +50,16 @@ def __repr__(self): elif self._closing: info.append('closing') if self._sock is not None: - info.append('fd=%s' % self._sock.fileno()) + info.append(f'fd={self._sock.fileno()}') if self._read_fut is not None: - info.append('read=%s' % self._read_fut) + info.append(f'read={self._read_fut!r}') if self._write_fut is not None: - info.append("write=%r" % self._write_fut) + info.append(f'write={self._write_fut!r}') if self._buffer: - bufsize = len(self._buffer) - info.append('write_bufsize=%s' % bufsize) + info.append(f'write_bufsize={len(self._buffer)}') if self._eof_written: info.append('EOF written') - return '<%s>' % ' '.join(info) + return '<{}>'.format(' '.join(info)) def _set_extra(self, sock): self._extra['pipe'] = sock @@ -87,7 +86,7 @@ def close(self): def __del__(self): if self._sock is not None: - warnings.warn("unclosed transport %r" % self, ResourceWarning, + warnings.warn(f"unclosed transport {self!r}", ResourceWarning, source=self) self.close() @@ -227,9 +226,9 @@ class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport, def write(self, data): if not isinstance(data, (bytes, bytearray, memoryview)): - msg = ("data argument must be a bytes-like object, not '%s'" % - type(data).__name__) - raise TypeError(msg) + raise TypeError( + f"data argument must be a bytes-like object, " + f"not {type(data).__name__}") if self._eof_written: raise RuntimeError('write_eof() already called') @@ -347,12 +346,14 @@ class _ProactorSocketTransport(_ProactorReadPipeTransport, def _set_extra(self, sock): self._extra['socket'] = sock + try: self._extra['sockname'] = sock.getsockname() except (socket.error, AttributeError): if self._loop.get_debug(): - logger.warning("getsockname() failed on %r", - sock, exc_info=True) + logger.warning( + "getsockname() failed on %r", sock, exc_info=True) + if 'peername' not in self._extra: try: self._extra['peername'] = sock.getpeername() diff --git a/Lib/asyncio/protocols.py b/Lib/asyncio/protocols.py index 80fcac9a82d..57987ae4463 100644 --- a/Lib/asyncio/protocols.py +++ b/Lib/asyncio/protocols.py @@ -1,7 +1,9 @@ -"""Abstract Protocol class.""" +"""Abstract Protocol base classes.""" -__all__ = ['BaseProtocol', 'Protocol', 'DatagramProtocol', - 'SubprocessProtocol'] +__all__ = ( + 'BaseProtocol', 'Protocol', 'DatagramProtocol', + 'SubprocessProtocol', +) class BaseProtocol: diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py index 10e694f1393..512ea6037f8 100644 --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -1,6 +1,4 @@ -"""Queues""" - -__all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty'] +__all__ = ('Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty') import collections import heapq @@ -10,16 +8,12 @@ class QueueEmpty(Exception): - """Exception raised when Queue.get_nowait() is called on a Queue object - which is empty. - """ + """Raised when Queue.get_nowait() is called on an empty Queue.""" pass class QueueFull(Exception): - """Exception raised when the Queue.put_nowait() method is called on a Queue - object which is full. - """ + """Raised when the Queue.put_nowait() method is called on a full Queue.""" pass @@ -73,22 +67,21 @@ def _wakeup_next(self, waiters): break def __repr__(self): - return '<{} at {:#x} {}>'.format( - type(self).__name__, id(self), self._format()) + return f'<{type(self).__name__} at {id(self):#x} {self._format()}>' def __str__(self): - return '<{} {}>'.format(type(self).__name__, self._format()) + return f'<{type(self).__name__} {self._format()}>' def _format(self): - result = 'maxsize={!r}'.format(self._maxsize) + result = f'maxsize={self._maxsize!r}' if getattr(self, '_queue', None): - result += ' _queue={!r}'.format(list(self._queue)) + result += f' _queue={list(self._queue)!r}' if self._getters: - result += ' _getters[{}]'.format(len(self._getters)) + result += f' _getters[{len(self._getters)}]' if self._putters: - result += ' _putters[{}]'.format(len(self._putters)) + result += f' _putters[{len(self._putters)}]' if self._unfinished_tasks: - result += ' tasks={}'.format(self._unfinished_tasks) + result += f' tasks={self._unfinished_tasks}' return result def qsize(self): diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index c30fde7f4da..2467e23e854 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -4,7 +4,7 @@ also includes support for signal handling, see the unix_events sub-module. """ -__all__ = ['BaseSelectorEventLoop'] +__all__ = 'BaseSelectorEventLoop', import collections import errno @@ -184,8 +184,8 @@ def _accept_connection(self, protocol_factory, sock, raise # The event loop will catch, log and ignore it. else: extra = {'peername': addr} - accept = self._accept_connection2(protocol_factory, conn, extra, - sslcontext, server) + accept = self._accept_connection2( + protocol_factory, conn, extra, sslcontext, server) self.create_task(accept) async def _accept_connection2(self, protocol_factory, conn, extra, @@ -214,8 +214,8 @@ def _accept_connection(self, protocol_factory, sock, except Exception as exc: if self._debug: context = { - 'message': ('Error on transport creation ' - 'for incoming connection'), + 'message': + 'Error on transport creation for incoming connection', 'exception': exc, } if protocol is not None: @@ -231,8 +231,7 @@ def _ensure_fd_no_transport(self, fd): fileno = int(fileno.fileno()) except (AttributeError, TypeError, ValueError): # This code matches selectors._fileobj_to_fd function. - raise ValueError("Invalid file object: " - "{!r}".format(fd)) from None + raise ValueError(f"Invalid file object: {fd!r}") from None try: transport = self._transports[fileno] except KeyError: @@ -240,8 +239,8 @@ def _ensure_fd_no_transport(self, fd): else: if not transport.is_closing(): raise RuntimeError( - 'File descriptor {!r} is used by transport {!r}'.format( - fd, transport)) + f'File descriptor {fd!r} is used by transport ' + f'{transport!r}') def _add_reader(self, fd, callback, *args): self._check_closed() @@ -389,10 +388,11 @@ def sock_recv_into(self, sock, buf): def _sock_recv_into(self, fut, registered_fd, sock, buf): # _sock_recv_into() can add itself as an I/O callback if the operation - # can't be done immediately. Don't use it directly, call sock_recv_into(). + # can't be done immediately. Don't use it directly, call + # sock_recv_into(). if registered_fd is not None: # Remove the callback early. It should be rare that the - # selector says the fd is ready but the call still returns + # selector says the FD is ready but the call still returns # EAGAIN, and I am willing to take a hit in that case in # order to simplify the common case. self.remove_reader(registered_fd) @@ -497,7 +497,7 @@ def _sock_connect_cb(self, fut, sock, address): err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) if err != 0: # Jump to any except clause below. - raise OSError(err, 'Connect call failed %s' % (address,)) + raise OSError(err, f'Connect call failed {address}') except (BlockingIOError, InterruptedError): # socket is still registered, the callback will be retried later pass @@ -596,7 +596,7 @@ def __repr__(self): info.append('closed') elif self._closing: info.append('closing') - info.append('fd=%s' % self._sock_fd) + info.append(f'fd={self._sock_fd}') # test if the transport was closed if self._loop is not None and not self._loop.is_closed(): polling = _test_selector_event(self._loop._selector, @@ -615,8 +615,8 @@ def __repr__(self): state = 'idle' bufsize = self.get_write_buffer_size() - info.append('write=<%s, bufsize=%s>' % (state, bufsize)) - return '<%s>' % ' '.join(info) + info.append(f'write=<{state}, bufsize={bufsize}>') + return '<{}>'.format(' '.join(info)) def abort(self): self._force_close(None) @@ -642,7 +642,7 @@ def close(self): def __del__(self): if self._sock is not None: - warnings.warn("unclosed transport %r" % self, ResourceWarning, + warnings.warn(f"unclosed transport {self!r}", ResourceWarning, source=self) self._sock.close() @@ -758,8 +758,8 @@ def _read_ready(self): def write(self, data): if not isinstance(data, (bytes, bytearray, memoryview)): - raise TypeError('data argument must be a bytes-like object, ' - 'not %r' % type(data).__name__) + raise TypeError(f'data argument must be a bytes-like object, ' + f'not {type(data).__name__!r}') if self._eof: raise RuntimeError('Cannot call write() after write_eof()') if not data: @@ -862,14 +862,14 @@ def _read_ready(self): def sendto(self, data, addr=None): if not isinstance(data, (bytes, bytearray, memoryview)): - raise TypeError('data argument must be a bytes-like object, ' - 'not %r' % type(data).__name__) + raise TypeError(f'data argument must be a bytes-like object, ' + f'not {type(data).__name__!r}') if not data: return if self._address and addr not in (None, self._address): - raise ValueError('Invalid address: must be None or %s' % - (self._address,)) + raise ValueError( + f'Invalid address: must be None or {self._address}') if self._conn_lost and self._address: if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES: @@ -891,8 +891,8 @@ def sendto(self, data, addr=None): self._protocol.error_received(exc) return except Exception as exc: - self._fatal_error(exc, - 'Fatal write error on datagram transport') + self._fatal_error( + exc, 'Fatal write error on datagram transport') return # Ensure that what we buffer is immutable. @@ -914,8 +914,8 @@ def _sendto_ready(self): self._protocol.error_received(exc) return except Exception as exc: - self._fatal_error(exc, - 'Fatal write error on datagram transport') + self._fatal_error( + exc, 'Fatal write error on datagram transport') return self._maybe_resume_protocol() # May append to buffer. diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index c231eb58ee5..0c8f01ad8f1 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -313,7 +313,7 @@ def close(self): def __del__(self): if not self._closed: - warnings.warn("unclosed transport %r" % self, ResourceWarning, + warnings.warn(f"unclosed transport {self!r}", ResourceWarning, source=self) self.close() @@ -365,8 +365,8 @@ def write(self, data): to be sent out asynchronously. """ if not isinstance(data, (bytes, bytearray, memoryview)): - raise TypeError("data: expecting a bytes-like instance, got {!r}" - .format(type(data).__name__)) + raise TypeError(f"data: expecting a bytes-like instance, " + f"got {type(data).__name__}") if not data: return self._ssl_protocol._write_appdata(data) @@ -399,7 +399,8 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, raise RuntimeError('stdlib ssl module not available') if not sslcontext: - sslcontext = _create_transport_context(server_side, server_hostname) + sslcontext = _create_transport_context( + server_side, server_hostname) self._server_side = server_side if server_hostname and not server_side: @@ -567,8 +568,8 @@ def _on_handshake_complete(self, handshake_exc): if not hasattr(self._sslcontext, 'check_hostname'): # Verify hostname if requested, Python 3.4+ uses check_hostname # and checks the hostname in do_handshake() - if (self._server_hostname - and self._sslcontext.verify_mode != ssl.CERT_NONE): + if (self._server_hostname and + self._sslcontext.verify_mode != ssl.CERT_NONE): ssl.match_hostname(peercert, self._server_hostname) except BaseException as exc: if self._loop.get_debug(): diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index baa9ec94439..eef2b895f1e 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -1,15 +1,13 @@ -"""Stream-related things.""" - -__all__ = ['StreamReader', 'StreamWriter', 'StreamReaderProtocol', - 'open_connection', 'start_server', - 'IncompleteReadError', - 'LimitOverrunError', - ] +__all__ = ( + 'StreamReader', 'StreamWriter', 'StreamReaderProtocol', + 'open_connection', 'start_server', + 'IncompleteReadError', 'LimitOverrunError', +) import socket if hasattr(socket, 'AF_UNIX'): - __all__.extend(['open_unix_connection', 'start_unix_server']) + __all__ += ('open_unix_connection', 'start_unix_server') from . import coroutines from . import events @@ -29,8 +27,8 @@ class IncompleteReadError(EOFError): - expected: total number of expected bytes (or None if unknown) """ def __init__(self, partial, expected): - super().__init__("%d bytes read on a total of %r expected bytes" - % (len(partial), expected)) + super().__init__(f'{len(partial)} bytes read on a total of ' + f'{expected!r} expected bytes') self.partial = partial self.expected = expected @@ -281,10 +279,10 @@ def __init__(self, transport, protocol, reader, loop): self._loop = loop def __repr__(self): - info = [self.__class__.__name__, 'transport=%r' % self._transport] + info = [self.__class__.__name__, f'transport={self._transport!r}'] if self._reader is not None: - info.append('reader=%r' % self._reader) - return '<%s>' % ' '.join(info) + info.append(f'reader={self._reader!r}') + return '<{}>'.format(' '.join(info)) @property def transport(self): @@ -356,20 +354,20 @@ def __init__(self, limit=_DEFAULT_LIMIT, loop=None): def __repr__(self): info = ['StreamReader'] if self._buffer: - info.append('%d bytes' % len(self._buffer)) + info.append(f'{len(self._buffer)} bytes') if self._eof: info.append('eof') if self._limit != _DEFAULT_LIMIT: - info.append('l=%d' % self._limit) + info.append(f'limit={self._limit}') if self._waiter: - info.append('w=%r' % self._waiter) + info.append(f'waiter={self._waiter!r}') if self._exception: - info.append('e=%r' % self._exception) + info.append(f'exception={self._exception!r}') if self._transport: - info.append('t=%r' % self._transport) + info.append(f'transport={self._transport!r}') if self._paused: info.append('paused') - return '<%s>' % ' '.join(info) + return '<{}>'.format(' '.join(info)) def exception(self): return self._exception @@ -440,8 +438,9 @@ def feed_data(self, data): # would have an unexpected behaviour. It would not possible to know # which coroutine would get the next data. if self._waiter is not None: - raise RuntimeError('%s() called while another coroutine is ' - 'already waiting for incoming data' % func_name) + raise RuntimeError( + f'{func_name}() called while another coroutine is ' + f'already waiting for incoming data') assert not self._eof, '_wait_for_data after EOF' diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py index dd3d10c8879..90fc00de833 100644 --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -1,4 +1,4 @@ -__all__ = ['create_subprocess_exec', 'create_subprocess_shell'] +__all__ = 'create_subprocess_exec', 'create_subprocess_shell' import subprocess @@ -29,12 +29,12 @@ def __init__(self, limit, loop): def __repr__(self): info = [self.__class__.__name__] if self.stdin is not None: - info.append('stdin=%r' % self.stdin) + info.append(f'stdin={self.stdin!r}') if self.stdout is not None: - info.append('stdout=%r' % self.stdout) + info.append(f'stdout={self.stdout!r}') if self.stderr is not None: - info.append('stderr=%r' % self.stderr) - return '<%s>' % ' '.join(info) + info.append(f'stderr={self.stderr!r}') + return '<{}>'.format(' '.join(info)) def connection_made(self, transport): self._transport = transport @@ -83,7 +83,7 @@ def pipe_connection_lost(self, fd, exc): reader = self.stderr else: reader = None - if reader != None: + if reader is not None: if exc is None: reader.feed_eof() else: @@ -114,7 +114,7 @@ def __init__(self, transport, protocol, loop): self.pid = transport.get_pid() def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.pid) + return f'<{self.__class__.__name__} {self.pid}>' @property def returncode(self): @@ -137,8 +137,8 @@ def kill(self): debug = self._loop.get_debug() self.stdin.write(input) if debug: - logger.debug('%r communicate: feed stdin (%s bytes)', - self, len(input)) + logger.debug( + '%r communicate: feed stdin (%s bytes)', self, len(input)) try: await self.stdin.drain() except (BrokenPipeError, ConnectionResetError) as exc: diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index c23d06afd7c..e0af5abdf23 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -1,10 +1,11 @@ """Support for tasks, coroutines and the scheduler.""" -__all__ = ['Task', - 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', - 'wait', 'wait_for', 'as_completed', 'sleep', 'async', - 'gather', 'shield', 'ensure_future', 'run_coroutine_threadsafe', - ] +__all__ = ( + 'Task', + 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', + 'wait', 'wait_for', 'as_completed', 'sleep', 'async', + 'gather', 'shield', 'ensure_future', 'run_coroutine_threadsafe', +) import concurrent.futures import functools @@ -158,8 +159,7 @@ def cancel(self): return True def _step(self, exc=None): - assert not self.done(), \ - '_step(): already done: {!r}, {!r}'.format(self, exc) + assert not self.done(), f'_step(): already done: {self!r}, {exc!r}' if self._must_cancel: if not isinstance(exc, futures.CancelledError): exc = futures.CancelledError() @@ -195,18 +195,15 @@ def _step(self, exc=None): if blocking is not None: # Yielded Future must come from Future.__iter__(). if result._loop is not self._loop: - self._loop.call_soon( - self._step, - RuntimeError( - 'Task {!r} got Future {!r} attached to a ' - 'different loop'.format(self, result))) + new_exc = RuntimeError( + f'Task {self!r} got Future ' + f'{result!r} attached to a different loop') + self._loop.call_soon(self._step, new_exc) elif blocking: if result is self: - self._loop.call_soon( - self._step, - RuntimeError( - 'Task cannot await on itself: {!r}'.format( - self))) + new_exc = RuntimeError( + f'Task cannot await on itself: {self!r}') + self._loop.call_soon(self._step, new_exc) else: result._asyncio_future_blocking = False result.add_done_callback(self._wakeup) @@ -215,28 +212,24 @@ def _step(self, exc=None): if self._fut_waiter.cancel(): self._must_cancel = False else: - self._loop.call_soon( - self._step, - RuntimeError( - 'yield was used instead of yield from ' - 'in task {!r} with {!r}'.format(self, result))) + new_exc = RuntimeError( + f'yield was used instead of yield from ' + f'in task {self!r} with {result!r}') + self._loop.call_soon(self._step, new_exc) + elif result is None: # Bare yield relinquishes control for one event loop iteration. self._loop.call_soon(self._step) elif inspect.isgenerator(result): # Yielding a generator is just wrong. - self._loop.call_soon( - self._step, - RuntimeError( - 'yield was used instead of yield from for ' - 'generator in task {!r} with {}'.format( - self, result))) + new_exc = RuntimeError( + f'yield was used instead of yield from for ' + f'generator in task {self!r} with {result}') + self._loop.call_soon(self._step, new_exc) else: # Yielding something else is an error. - self._loop.call_soon( - self._step, - RuntimeError( - 'Task got bad yield: {!r}'.format(result))) + new_exc = RuntimeError(f'Task got bad yield: {result!r}') + self._loop.call_soon(self._step, new_exc) finally: self.__class__._current_tasks.pop(self._loop) self = None # Needed to break cycles when an exception occurs. @@ -294,11 +287,11 @@ def _wakeup(self, future): when the timeout occurs are returned in the second set. """ if futures.isfuture(fs) or coroutines.iscoroutine(fs): - raise TypeError("expect a list of futures, not %s" % type(fs).__name__) + raise TypeError(f"expect a list of futures, not {type(fs).__name__}") if not fs: raise ValueError('Set of coroutines/Futures is empty.') if return_when not in (FIRST_COMPLETED, FIRST_EXCEPTION, ALL_COMPLETED): - raise ValueError('Invalid return_when value: {}'.format(return_when)) + raise ValueError(f'Invalid return_when value: {return_when}') if loop is None: loop = events.get_event_loop() @@ -430,7 +423,7 @@ def as_completed(fs, *, loop=None, timeout=None): Note: The futures 'f' are not necessarily members of fs. """ if futures.isfuture(fs) or coroutines.iscoroutine(fs): - raise TypeError("expect a list of futures, not %s" % type(fs).__name__) + raise TypeError(f"expect a list of futures, not {type(fs).__name__}") loop = loop if loop is not None else events.get_event_loop() todo = {ensure_future(f, loop=loop) for f in set(fs)} from .queues import Queue # Import here to avoid circular import problem. diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py index a94079f433a..51f56737c67 100644 --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -1,8 +1,9 @@ """Abstract Transport class.""" -__all__ = ['BaseTransport', 'ReadTransport', 'WriteTransport', - 'Transport', 'DatagramTransport', 'SubprocessTransport', - ] +__all__ = ( + 'BaseTransport', 'ReadTransport', 'WriteTransport', + 'Transport', 'DatagramTransport', 'SubprocessTransport', +) class BaseTransport: @@ -267,7 +268,7 @@ def _maybe_pause_protocol(self): def _maybe_resume_protocol(self): if (self._protocol_paused and - self.get_write_buffer_size() <= self._low_water): + self.get_write_buffer_size() <= self._low_water): self._protocol_paused = False try: self._protocol.resume_writing() @@ -285,14 +286,16 @@ def get_write_buffer_limits(self): def _set_write_buffer_limits(self, high=None, low=None): if high is None: if low is None: - high = 64*1024 + high = 64 * 1024 else: - high = 4*low + high = 4 * low if low is None: low = high // 4 + if not high >= low >= 0: - raise ValueError('high (%r) must be >= low (%r) must be >= 0' % - (high, low)) + raise ValueError( + f'high ({high!r}) must be >= low ({low!r}) must be >= 0') + self._high_water = high self._low_water = low diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 0308b02a52d..b9bdf8786f2 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -23,10 +23,12 @@ from .log import logger -__all__ = ['SelectorEventLoop', - 'AbstractChildWatcher', 'SafeChildWatcher', - 'FastChildWatcher', 'DefaultEventLoopPolicy', - ] +__all__ = ( + 'SelectorEventLoop', + 'AbstractChildWatcher', 'SafeChildWatcher', + 'FastChildWatcher', 'DefaultEventLoopPolicy', +) + if sys.platform == 'win32': # pragma: no cover raise ImportError('Signals are not really supported on Windows') @@ -65,8 +67,8 @@ def add_signal_handler(self, sig, callback, *args): Raise ValueError if the signal number is invalid or uncatchable. Raise RuntimeError if there is a problem setting up the handler. """ - if (coroutines.iscoroutine(callback) - or coroutines.iscoroutinefunction(callback)): + if (coroutines.iscoroutine(callback) or + coroutines.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used " "with add_signal_handler()") self._check_signal(sig) @@ -100,7 +102,7 @@ def add_signal_handler(self, sig, callback, *args): logger.info('set_wakeup_fd(-1) failed: %s', nexc) if exc.errno == errno.EINVAL: - raise RuntimeError('sig {} cannot be caught'.format(sig)) + raise RuntimeError(f'sig {sig} cannot be caught') else: raise @@ -134,7 +136,7 @@ def remove_signal_handler(self, sig): signal.signal(sig, handler) except OSError as exc: if exc.errno == errno.EINVAL: - raise RuntimeError('sig {} cannot be caught'.format(sig)) + raise RuntimeError(f'sig {sig} cannot be caught') else: raise @@ -153,11 +155,10 @@ def _check_signal(self, sig): Raise RuntimeError if there is a problem setting up the handler. """ if not isinstance(sig, int): - raise TypeError('sig must be an int, not {!r}'.format(sig)) + raise TypeError(f'sig must be an int, not {sig!r}') if not (1 <= sig < signal.NSIG): - raise ValueError( - 'sig {} out of range(1, {})'.format(sig, signal.NSIG)) + raise ValueError(f'sig {sig} out of range(1, {signal.NSIG})') def _make_read_pipe_transport(self, pipe, protocol, waiter=None, extra=None): @@ -223,8 +224,7 @@ def _child_watcher_callback(self, pid, returncode, transp): if (sock.family != socket.AF_UNIX or not base_events._is_stream_socket(sock)): raise ValueError( - 'A UNIX Domain Stream Socket was expected, got {!r}' - .format(sock)) + f'A UNIX Domain Stream Socket was expected, got {sock!r}') sock.setblocking(False) transport, protocol = await self._create_connection_transport( @@ -263,7 +263,7 @@ def _child_watcher_callback(self, pid, returncode, transp): if exc.errno == errno.EADDRINUSE: # Let's improve the error message by adding # with what exact address it occurs. - msg = 'Address {!r} is already in use'.format(path) + msg = f'Address {path!r} is already in use' raise OSError(errno.EADDRINUSE, msg) from None else: raise @@ -278,8 +278,7 @@ def _child_watcher_callback(self, pid, returncode, transp): if (sock.family != socket.AF_UNIX or not base_events._is_stream_socket(sock)): raise ValueError( - 'A UNIX Domain Stream Socket was expected, got {!r}' - .format(sock)) + f'A UNIX Domain Stream Socket was expected, got {sock!r}') server = base_events.Server(self, [sock]) sock.listen(backlog) @@ -327,12 +326,11 @@ def __repr__(self): info.append('closed') elif self._closing: info.append('closing') - info.append('fd=%s' % self._fileno) + info.append(f'fd={self._fileno}') selector = getattr(self._loop, '_selector', None) if self._pipe is not None and selector is not None: polling = selector_events._test_selector_event( - selector, - self._fileno, selectors.EVENT_READ) + selector, self._fileno, selectors.EVENT_READ) if polling: info.append('polling') else: @@ -341,7 +339,7 @@ def __repr__(self): info.append('open') else: info.append('closed') - return '<%s>' % ' '.join(info) + return '<{}>'.format(' '.join(info)) def _read_ready(self): try: @@ -382,7 +380,7 @@ def close(self): def __del__(self): if self._pipe is not None: - warnings.warn("unclosed transport %r" % self, ResourceWarning, + warnings.warn(f"unclosed transport {self!r}", ResourceWarning, source=self) self._pipe.close() @@ -461,24 +459,23 @@ def __repr__(self): info.append('closed') elif self._closing: info.append('closing') - info.append('fd=%s' % self._fileno) + info.append(f'fd={self._fileno}') selector = getattr(self._loop, '_selector', None) if self._pipe is not None and selector is not None: polling = selector_events._test_selector_event( - selector, - self._fileno, selectors.EVENT_WRITE) + selector, self._fileno, selectors.EVENT_WRITE) if polling: info.append('polling') else: info.append('idle') bufsize = self.get_write_buffer_size() - info.append('bufsize=%s' % bufsize) + info.append(f'bufsize={bufsize}') elif self._pipe is not None: info.append('open') else: info.append('closed') - return '<%s>' % ' '.join(info) + return '<{}>'.format(' '.join(info)) def get_write_buffer_size(self): return len(self._buffer) @@ -579,7 +576,7 @@ def close(self): def __del__(self): if self._pipe is not None: - warnings.warn("unclosed transport %r" % self, ResourceWarning, + warnings.warn(f"unclosed transport {self!r}", ResourceWarning, source=self) self._pipe.close() @@ -1007,5 +1004,6 @@ def set_child_watcher(self, watcher): self._watcher = watcher + SelectorEventLoop = _UnixSelectorEventLoop DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index 95b12a11a62..e18fd392ba2 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -18,9 +18,10 @@ from .log import logger -__all__ = ['SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor', - 'DefaultEventLoopPolicy', - ] +__all__ = ( + 'SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor', + 'DefaultEventLoopPolicy', +) NULL = 0 @@ -51,7 +52,7 @@ def _repr_info(self): info = super()._repr_info() if self._ov is not None: state = 'pending' if self._ov.pending else 'completed' - info.insert(1, 'overlapped=<%s, %#x>' % (state, self._ov.address)) + info.insert(1, f'overlapped=<{state}, {self._ov.address:#x}>') return info def _cancel_overlapped(self): @@ -107,12 +108,12 @@ def _poll(self): def _repr_info(self): info = super()._repr_info() - info.append('handle=%#x' % self._handle) + info.append(f'handle={self._handle:#x}') if self._handle is not None: state = 'signaled' if self._poll() else 'waiting' info.append(state) if self._wait_handle is not None: - info.append('wait_handle=%#x' % self._wait_handle) + info.append(f'wait_handle={self._wait_handle:#x}') return info def _unregister_wait_cb(self, fut): @@ -543,9 +544,9 @@ def finish_accept_pipe(trans, key, ov): async def connect_pipe(self, address): delay = CONNECT_PIPE_INIT_DELAY while True: - # Unfortunately there is no way to do an overlapped connect to a pipe. - # Call CreateFile() in a loop until it doesn't fail with - # ERROR_PIPE_BUSY + # Unfortunately there is no way to do an overlapped connect to + # a pipe. Call CreateFile() in a loop until it doesn't fail with + # ERROR_PIPE_BUSY. try: handle = _overlapped.ConnectPipe(address) break diff --git a/Lib/asyncio/windows_utils.py b/Lib/asyncio/windows_utils.py index 3b410976f9d..9e22f6e0740 100644 --- a/Lib/asyncio/windows_utils.py +++ b/Lib/asyncio/windows_utils.py @@ -1,6 +1,4 @@ -""" -Various Windows specific bits and pieces -""" +"""Various Windows specific bits and pieces.""" import sys @@ -11,13 +9,12 @@ import itertools import msvcrt import os -import socket import subprocess import tempfile import warnings -__all__ = ['pipe', 'Popen', 'PIPE', 'PipeHandle'] +__all__ = 'pipe', 'Popen', 'PIPE', 'PipeHandle' # Constants/globals @@ -34,8 +31,9 @@ def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE): """Like os.pipe() but with overlapped support and using handles not fds.""" - address = tempfile.mktemp(prefix=r'\\.\pipe\python-pipe-%d-%d-' % - (os.getpid(), next(_mmap_counter))) + address = tempfile.mktemp( + prefix=r'\\.\pipe\python-pipe-{:d}-{:d}-'.format( + os.getpid(), next(_mmap_counter))) if duplex: openmode = _winapi.PIPE_ACCESS_DUPLEX @@ -90,10 +88,10 @@ def __init__(self, handle): def __repr__(self): if self._handle is not None: - handle = 'handle=%r' % self._handle + handle = f'handle={self._handle!r}' else: handle = 'closed' - return '<%s %s>' % (self.__class__.__name__, handle) + return f'<{self.__class__.__name__} {handle}>' @property def handle(self): @@ -111,7 +109,7 @@ def close(self, *, CloseHandle=_winapi.CloseHandle): def __del__(self): if self._handle is not None: - warnings.warn("unclosed %r" % self, ResourceWarning, + warnings.warn(f"unclosed {self!r}", ResourceWarning, source=self) self.close() diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index f365a45106e..78d80ecf4f3 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -10,7 +10,7 @@ STR_RGX_REPR = ( r'^<(?P.*?) object at (?P
.*?)' r'\[(?P' - r'(set|unset|locked|unlocked)(,value:\d)?(,waiters:\d+)?' + r'(set|unset|locked|unlocked)(, value:\d)?(, waiters:\d+)?' r')\]>\Z' ) RGX_REPR = re.compile(STR_RGX_REPR) @@ -760,7 +760,7 @@ def test_initial_value_zero(self): def test_repr(self): sem = asyncio.Semaphore(loop=self.loop) - self.assertTrue(repr(sem).endswith('[unlocked,value:1]>')) + self.assertTrue(repr(sem).endswith('[unlocked, value:1]>')) self.assertTrue(RGX_REPR.match(repr(sem))) self.loop.run_until_complete(sem.acquire()) diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 2f4e6d23bf9..1927d731281 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -806,7 +806,7 @@ def test___repr__(self): def test___repr__nondefault_limit(self): stream = asyncio.StreamReader(loop=self.loop, limit=123) - self.assertEqual("", repr(stream)) + self.assertEqual("", repr(stream)) def test___repr__eof(self): stream = asyncio.StreamReader(loop=self.loop) @@ -822,14 +822,15 @@ def test___repr__exception(self): stream = asyncio.StreamReader(loop=self.loop) exc = RuntimeError() stream.set_exception(exc) - self.assertEqual("", repr(stream)) + self.assertEqual("", + repr(stream)) def test___repr__waiter(self): stream = asyncio.StreamReader(loop=self.loop) stream._waiter = asyncio.Future(loop=self.loop) self.assertRegex( repr(stream), - r">") + r">") stream._waiter.set_result(None) self.loop.run_until_complete(stream._waiter) stream._waiter = None @@ -840,7 +841,7 @@ def test___repr__transport(self): stream._transport = mock.Mock() stream._transport.__repr__ = mock.Mock() stream._transport.__repr__.return_value = "" - self.assertEqual(">", repr(stream)) + self.assertEqual(">", repr(stream)) def test_IncompleteReadError_pickleable(self): e = asyncio.IncompleteReadError(b'abc', 10) From webhook-mailer at python.org Sun Dec 10 19:52:55 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 11 Dec 2017 00:52:55 -0000 Subject: [Python-checkins] bpo-32262: Fix f-string (#4787) Message-ID: https://github.com/python/cpython/commit/19d0d5480931117d9e0bf396a0234707bbdaa494 commit: 19d0d5480931117d9e0bf396a0234707bbdaa494 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-10T19:52:53-05:00 summary: bpo-32262: Fix f-string (#4787) files: M Lib/asyncio/base_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 5cc7944f24a..9584d6355f8 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -631,7 +631,7 @@ def set_default_executor(self, executor): def _getaddrinfo_debug(self, host, port, family, type, proto, flags): msg = [f"{host}:{port!r}"] if family: - msg.append(f'family={family!r}' % family) + msg.append(f'family={family!r}') if type: msg.append(f'type={type!r}') if proto: From solipsis at pitrou.net Mon Dec 11 04:14:40 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 11 Dec 2017 09:14:40 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=9 Message-ID: <20171211091440.118256.1556396B8C9DC263@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, 2, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogXQzbWe', '--timeout', '7200'] From webhook-mailer at python.org Mon Dec 11 07:57:16 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 11 Dec 2017 12:57:16 -0000 Subject: [Python-checkins] bpo-32252: Fix faulthandler_suppress_crash_report() (#4794) Message-ID: https://github.com/python/cpython/commit/48d4dd974f0c8d47c54990eedd322b96b19c60ec commit: 48d4dd974f0c8d47c54990eedd322b96b19c60ec branch: master author: Victor Stinner committer: GitHub date: 2017-12-11T13:57:12+01:00 summary: bpo-32252: Fix faulthandler_suppress_crash_report() (#4794) Fix faulthandler_suppress_crash_report() used to prevent core dump files when testing crashes. getrlimit() returns zero on success. files: A Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst M Modules/faulthandler.c diff --git a/Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst b/Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst new file mode 100644 index 00000000000..ee4c56bb73f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst @@ -0,0 +1,2 @@ +Fix faulthandler_suppress_crash_report() used to prevent core dump files +when testing crashes. getrlimit() returns zero on success. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 0e85cce132f..baa2e917706 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -932,7 +932,7 @@ faulthandler_suppress_crash_report(void) struct rlimit rl; /* Disable creation of core dump */ - if (getrlimit(RLIMIT_CORE, &rl) != 0) { + if (getrlimit(RLIMIT_CORE, &rl) == 0) { rl.rlim_cur = 0; setrlimit(RLIMIT_CORE, &rl); } From webhook-mailer at python.org Mon Dec 11 08:17:10 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 11 Dec 2017 13:17:10 -0000 Subject: [Python-checkins] bpo-32252: Fix faulthandler_suppress_crash_report() (GH-4794) (#4795) Message-ID: https://github.com/python/cpython/commit/71d8f36eb450cdbc4b5397e25f6f3f5d676aca79 commit: 71d8f36eb450cdbc4b5397e25f6f3f5d676aca79 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Victor Stinner date: 2017-12-11T14:17:06+01:00 summary: bpo-32252: Fix faulthandler_suppress_crash_report() (GH-4794) (#4795) Fix faulthandler_suppress_crash_report() used to prevent core dump files when testing crashes. getrlimit() returns zero on success. (cherry picked from commit 48d4dd974f0c8d47c54990eedd322b96b19c60ec) files: A Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst M Modules/faulthandler.c diff --git a/Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst b/Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst new file mode 100644 index 00000000000..ee4c56bb73f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-12-11-13-31-33.bpo-32252.YnFw7J.rst @@ -0,0 +1,2 @@ +Fix faulthandler_suppress_crash_report() used to prevent core dump files +when testing crashes. getrlimit() returns zero on success. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index d5194cad610..92aa1d444bb 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -936,7 +936,7 @@ faulthandler_suppress_crash_report(void) struct rlimit rl; /* Disable creation of core dump */ - if (getrlimit(RLIMIT_CORE, &rl) != 0) { + if (getrlimit(RLIMIT_CORE, &rl) == 0) { rl.rlim_cur = 0; setrlimit(RLIMIT_CORE, &rl); } From webhook-mailer at python.org Mon Dec 11 08:42:16 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 11 Dec 2017 13:42:16 -0000 Subject: [Python-checkins] bpo-22671: Clarify and test default read method implementations (#4568) Message-ID: https://github.com/python/cpython/commit/1b74f9b77a6fa1d7828986cb79d5b10942ff9141 commit: 1b74f9b77a6fa1d7828986cb79d5b10942ff9141 branch: master author: Sanyam Khurana <8039608+CuriousLearner at users.noreply.github.com> committer: Victor Stinner date: 2017-12-11T14:42:09+01:00 summary: bpo-22671: Clarify and test default read method implementations (#4568) Original patch written by Martin Panter, enhanced by Sanyam Khurana. files: M Doc/library/io.rst M Lib/test/test_io.py diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 8a695ad99dd..6778058342d 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -205,8 +205,8 @@ ABC Inherits Stub Methods Mixin M ``writable``, and ``writelines`` :class:`RawIOBase` :class:`IOBase` ``readinto`` and Inherited :class:`IOBase` methods, ``read``, ``write`` and ``readall`` -:class:`BufferedIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``readinto`` - ``read1``, and ``write`` +:class:`BufferedIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``readinto``, + ``read1``, and ``write`` and ``readinto1`` :class:`TextIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``encoding``, ``readline``, and ``errors``, and ``newlines`` ``write`` @@ -385,14 +385,17 @@ I/O Base Classes .. method:: read(size=-1) Read up to *size* bytes from the object and return them. As a convenience, - if *size* is unspecified or -1, :meth:`readall` is called. Otherwise, - only one system call is ever made. Fewer than *size* bytes may be - returned if the operating system call returns fewer than *size* bytes. + if *size* is unspecified or -1, all bytes until EOF are returned. + Otherwise, only one system call is ever made. Fewer than *size* bytes may + be returned if the operating system call returns fewer than *size* bytes. If 0 bytes are returned, and *size* was not 0, this indicates end of file. If the object is in non-blocking mode and no bytes are available, ``None`` is returned. + The default implementation defers to :meth:`readall` and + :meth:`readinto`. + .. method:: readall() Read and return all the bytes from the stream until EOF, using multiple diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 2ac2e17a03e..6bb4127b095 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -807,8 +807,8 @@ def test_multi_close(self): self.assertRaises(ValueError, f.flush) def test_RawIOBase_read(self): - # Exercise the default RawIOBase.read() implementation (which calls - # readinto() internally). + # Exercise the default limited RawIOBase.read(n) implementation (which + # calls readinto() internally). rawio = self.MockRawIOWithoutRead((b"abc", b"d", None, b"efg", None)) self.assertEqual(rawio.read(2), b"ab") self.assertEqual(rawio.read(2), b"c") @@ -916,6 +916,55 @@ def check_path_succeeds(path): with self.assertRaisesRegex(ValueError, 'read/write/append mode'): self.open(PathLike(support.TESTFN), 'rwxa') + def test_RawIOBase_readall(self): + # Exercise the default unlimited RawIOBase.read() and readall() + # implementations. + rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg")) + self.assertEqual(rawio.read(), b"abcdefg") + rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg")) + self.assertEqual(rawio.readall(), b"abcdefg") + + def test_BufferedIOBase_readinto(self): + # Exercise the default BufferedIOBase.readinto() and readinto1() + # implementations (which call read() or read1() internally). + class Reader(self.BufferedIOBase): + def __init__(self, avail): + self.avail = avail + def read(self, size): + result = self.avail[:size] + self.avail = self.avail[size:] + return result + def read1(self, size): + """Returns no more than 5 bytes at once""" + return self.read(min(size, 5)) + tests = ( + # (test method, total data available, read buffer size, expected + # read size) + ("readinto", 10, 5, 5), + ("readinto", 10, 6, 6), # More than read1() can return + ("readinto", 5, 6, 5), # Buffer larger than total available + ("readinto", 6, 7, 6), + ("readinto", 10, 0, 0), # Empty buffer + ("readinto1", 10, 5, 5), # Result limited to single read1() call + ("readinto1", 10, 6, 5), # Buffer larger than read1() can return + ("readinto1", 5, 6, 5), # Buffer larger than total available + ("readinto1", 6, 7, 5), + ("readinto1", 10, 0, 0), # Empty buffer + ) + UNUSED_BYTE = 0x81 + for test in tests: + with self.subTest(test): + method, avail, request, result = test + reader = Reader(bytes(range(avail))) + buffer = bytearray((UNUSED_BYTE,) * request) + method = getattr(reader, method) + self.assertEqual(method(buffer), result) + self.assertEqual(len(buffer), request) + self.assertSequenceEqual(buffer[:result], range(result)) + unused = (UNUSED_BYTE,) * (request - result) + self.assertSequenceEqual(buffer[result:], unused) + self.assertEqual(len(reader.avail), avail - result) + class CIOTest(IOTest): From webhook-mailer at python.org Mon Dec 11 09:27:33 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 11 Dec 2017 14:27:33 -0000 Subject: [Python-checkins] bpo-22671: Clarify and test default read method implementations (GH-4568) (#4796) Message-ID: https://github.com/python/cpython/commit/0aa2a1d003b476b954ecdcb7e966bf7f0b75a06b commit: 0aa2a1d003b476b954ecdcb7e966bf7f0b75a06b branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Victor Stinner date: 2017-12-11T15:27:25+01:00 summary: bpo-22671: Clarify and test default read method implementations (GH-4568) (#4796) Original patch written by Martin Panter, enhanced by Sanyam Khurana. (cherry picked from commit 1b74f9b77a6fa1d7828986cb79d5b10942ff9141) files: M Doc/library/io.rst M Lib/test/test_io.py diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 4da6e095d17..af38fd72758 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -205,8 +205,8 @@ ABC Inherits Stub Methods Mixin M ``writable``, and ``writelines`` :class:`RawIOBase` :class:`IOBase` ``readinto`` and Inherited :class:`IOBase` methods, ``read``, ``write`` and ``readall`` -:class:`BufferedIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``readinto`` - ``read1``, and ``write`` +:class:`BufferedIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``readinto``, + ``read1``, and ``write`` and ``readinto1`` :class:`TextIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``encoding``, ``readline``, and ``errors``, and ``newlines`` ``write`` @@ -385,14 +385,17 @@ I/O Base Classes .. method:: read(size=-1) Read up to *size* bytes from the object and return them. As a convenience, - if *size* is unspecified or -1, :meth:`readall` is called. Otherwise, - only one system call is ever made. Fewer than *size* bytes may be - returned if the operating system call returns fewer than *size* bytes. + if *size* is unspecified or -1, all bytes until EOF are returned. + Otherwise, only one system call is ever made. Fewer than *size* bytes may + be returned if the operating system call returns fewer than *size* bytes. If 0 bytes are returned, and *size* was not 0, this indicates end of file. If the object is in non-blocking mode and no bytes are available, ``None`` is returned. + The default implementation defers to :meth:`readall` and + :meth:`readinto`. + .. method:: readall() Read and return all the bytes from the stream until EOF, using multiple diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 08c041ed937..c81672325ba 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -796,8 +796,8 @@ def test_multi_close(self): self.assertRaises(ValueError, f.flush) def test_RawIOBase_read(self): - # Exercise the default RawIOBase.read() implementation (which calls - # readinto() internally). + # Exercise the default limited RawIOBase.read(n) implementation (which + # calls readinto() internally). rawio = self.MockRawIOWithoutRead((b"abc", b"d", None, b"efg", None)) self.assertEqual(rawio.read(2), b"ab") self.assertEqual(rawio.read(2), b"c") @@ -905,6 +905,55 @@ def check_path_succeeds(path): with self.assertRaisesRegex(ValueError, 'read/write/append mode'): self.open(PathLike(support.TESTFN), 'rwxa') + def test_RawIOBase_readall(self): + # Exercise the default unlimited RawIOBase.read() and readall() + # implementations. + rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg")) + self.assertEqual(rawio.read(), b"abcdefg") + rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg")) + self.assertEqual(rawio.readall(), b"abcdefg") + + def test_BufferedIOBase_readinto(self): + # Exercise the default BufferedIOBase.readinto() and readinto1() + # implementations (which call read() or read1() internally). + class Reader(self.BufferedIOBase): + def __init__(self, avail): + self.avail = avail + def read(self, size): + result = self.avail[:size] + self.avail = self.avail[size:] + return result + def read1(self, size): + """Returns no more than 5 bytes at once""" + return self.read(min(size, 5)) + tests = ( + # (test method, total data available, read buffer size, expected + # read size) + ("readinto", 10, 5, 5), + ("readinto", 10, 6, 6), # More than read1() can return + ("readinto", 5, 6, 5), # Buffer larger than total available + ("readinto", 6, 7, 6), + ("readinto", 10, 0, 0), # Empty buffer + ("readinto1", 10, 5, 5), # Result limited to single read1() call + ("readinto1", 10, 6, 5), # Buffer larger than read1() can return + ("readinto1", 5, 6, 5), # Buffer larger than total available + ("readinto1", 6, 7, 5), + ("readinto1", 10, 0, 0), # Empty buffer + ) + UNUSED_BYTE = 0x81 + for test in tests: + with self.subTest(test): + method, avail, request, result = test + reader = Reader(bytes(range(avail))) + buffer = bytearray((UNUSED_BYTE,) * request) + method = getattr(reader, method) + self.assertEqual(method(buffer), result) + self.assertEqual(len(buffer), request) + self.assertSequenceEqual(buffer[:result], range(result)) + unused = (UNUSED_BYTE,) * (request - result) + self.assertSequenceEqual(buffer[result:], unused) + self.assertEqual(len(reader.avail), avail - result) + class CIOTest(IOTest): From webhook-mailer at python.org Mon Dec 11 10:03:51 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 11 Dec 2017 15:03:51 -0000 Subject: [Python-checkins] bpo-32272: Remove asyncio.async() function. (#4784) Message-ID: https://github.com/python/cpython/commit/9edad3c7011ccab0a66a065933abebf3288cf1a1 commit: 9edad3c7011ccab0a66a065933abebf3288cf1a1 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-11T10:03:48-05:00 summary: bpo-32272: Remove asyncio.async() function. (#4784) files: A Misc/NEWS.d/next/Library/2017-12-10-18-59-13.bpo-32272.Mu84Am.rst M Doc/library/asyncio-eventloop.rst M Doc/library/asyncio-task.rst M Lib/asyncio/tasks.py diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 760640fa5e4..c582b2779b0 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -235,9 +235,6 @@ Tasks interoperability. In this case, the result type is a subclass of :class:`Task`. - This method was added in Python 3.4.2. Use the :func:`async` function to - support also older Python versions. - .. versionadded:: 3.4.2 .. method:: AbstractEventLoop.set_task_factory(factory) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index ff35b0add9d..3656f793deb 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -538,12 +538,6 @@ Task functions The :meth:`AbstractEventLoop.create_task` method. -.. function:: async(coro_or_future, \*, loop=None) - - A deprecated alias to :func:`ensure_future`. - - .. deprecated:: 3.4.4 - .. function:: wrap_future(future, \*, loop=None) Wrap a :class:`concurrent.futures.Future` object in a :class:`Future` diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index e0af5abdf23..c5122f76071 100644 --- 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', + 'wait', 'wait_for', 'as_completed', 'sleep', 'gather', 'shield', 'ensure_future', 'run_coroutine_threadsafe', ) @@ -489,26 +489,6 @@ def __sleep0(): h.cancel() -def async_(coro_or_future, *, loop=None): - """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, - stacklevel=2) - - return ensure_future(coro_or_future, loop=loop) - -# Silence DeprecationWarning: -globals()['async'] = async_ -async_.__name__ = 'async' -del async_ - - def ensure_future(coro_or_future, *, loop=None): """Wrap a coroutine or an awaitable in a future. diff --git a/Misc/NEWS.d/next/Library/2017-12-10-18-59-13.bpo-32272.Mu84Am.rst b/Misc/NEWS.d/next/Library/2017-12-10-18-59-13.bpo-32272.Mu84Am.rst new file mode 100644 index 00000000000..500e3c8c2a5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-10-18-59-13.bpo-32272.Mu84Am.rst @@ -0,0 +1 @@ +Remove asyncio.async() function. From webhook-mailer at python.org Mon Dec 11 10:04:43 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 11 Dec 2017 15:04:43 -0000 Subject: [Python-checkins] bpo-32273: Move asyncio.test_utils to test.test_asyncio (#4785) Message-ID: https://github.com/python/cpython/commit/3e9751819ad13a965e8be13c1e5bc5a6811fe6b8 commit: 3e9751819ad13a965e8be13c1e5bc5a6811fe6b8 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-11T10:04:40-05:00 summary: bpo-32273: Move asyncio.test_utils to test.test_asyncio (#4785) files: A Lib/test/test_asyncio/utils.py A Misc/NEWS.d/next/Library/2017-12-10-19-14-55.bpo-32273.5KKlCv.rst D Lib/asyncio/test_utils.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_locks.py M Lib/test/test_asyncio/test_pep492.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_queues.py M Lib/test/test_asyncio/test_selector_events.py M Lib/test/test_asyncio/test_sslproto.py M Lib/test/test_asyncio/test_streams.py M Lib/test/test_asyncio/test_subprocess.py M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_asyncio/test_unix_events.py M Lib/test/test_asyncio/test_windows_events.py M Lib/test/test_asyncio/test_windows_utils.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 6561a9df779..8b08ed16634 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -14,18 +14,9 @@ import asyncio from asyncio import base_events from asyncio import constants -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: - try: - from test.script_helper import assert_python_ok - except ImportError: - from asyncio.test_support import assert_python_ok +from test.test_asyncio import utils as test_utils +from test import support +from test.support.script_helper import assert_python_ok MOCK_ANY = mock.ANY diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 01300246fda..39d5bb54a9d 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -3,7 +3,6 @@ import collections.abc import concurrent.futures import functools -import gc import io import os import platform @@ -30,8 +29,7 @@ from asyncio import coroutines from asyncio import proactor_events from asyncio import selector_events -from asyncio import sslproto -from asyncio import test_utils +from test.test_asyncio import utils as test_utils try: from test import support except ImportError: diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 4320a901f49..444d1df02be 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -9,12 +9,9 @@ from unittest import mock import asyncio -from asyncio import test_utils from asyncio import futures -try: - from test import support -except ImportError: - from asyncio import test_support as support +from test.test_asyncio import utils as test_utils +from test import support def _fakefunc(f): diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 78d80ecf4f3..3c5069778b5 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -5,7 +5,7 @@ import re import asyncio -from asyncio import test_utils +from test.test_asyncio import utils as test_utils STR_RGX_REPR = ( r'^<(?P.*?) object at (?P
.*?)' diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py index 442577017d9..8dd0c25e7cf 100644 --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -3,14 +3,11 @@ import types import unittest -try: - from test import support -except ImportError: - from asyncio import test_support as support +from test import support from unittest import mock import asyncio -from asyncio import test_utils +from test.test_asyncio import utils as test_utils class BaseTest(test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index def08b96ab0..7ccc6814b2e 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -9,7 +9,7 @@ from asyncio.proactor_events import _ProactorSocketTransport from asyncio.proactor_events import _ProactorWritePipeTransport from asyncio.proactor_events import _ProactorDuplexPipeTransport -from asyncio import test_utils +from test.test_asyncio import utils as test_utils def close_transport(transport): diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py index 3b66d616f8e..8d78546318a 100644 --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -4,7 +4,7 @@ from unittest import mock import asyncio -from asyncio import test_utils +from test.test_asyncio import utils as test_utils class _QueueTestBase(test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 616eb6f2630..24feb30e3d5 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -11,11 +11,11 @@ ssl = None import asyncio -from asyncio import test_utils from asyncio.selector_events import BaseSelectorEventLoop from asyncio.selector_events import _SelectorTransport from asyncio.selector_events import _SelectorSocketTransport from asyncio.selector_events import _SelectorDatagramTransport +from test.test_asyncio import utils as test_utils MOCK_ANY = mock.ANY diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index f573ae8fe77..7650fe6bd46 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -11,7 +11,7 @@ import asyncio from asyncio import log from asyncio import sslproto -from asyncio import test_utils +from test.test_asyncio import utils as test_utils @unittest.skipIf(ssl is None, 'No ssl module') diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 1927d731281..7a0762cfa3b 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -16,7 +16,7 @@ ssl = None import asyncio -from asyncio import test_utils +from test.test_asyncio import utils as test_utils class StreamReaderTests(test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index ad4bb149559..81b08d6c292 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -7,11 +7,9 @@ import asyncio from asyncio import base_subprocess from asyncio import subprocess -from asyncio import test_utils -try: - from test import support -except ImportError: - from asyncio import test_support as support +from test.test_asyncio import utils as test_utils +from test import support + if sys.platform != 'win32': from asyncio import unix_events diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index cdc882a9bee..071481dbc26 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -17,18 +17,9 @@ from asyncio import coroutines from asyncio import futures from asyncio import tasks -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: - try: - from test.script_helper import assert_python_ok - except ImportError: - from asyncio.test_support import assert_python_ok +from test.test_asyncio import utils as test_utils +from test import support +from test.support.script_helper import assert_python_ok @asyncio.coroutine diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 6746b34fe2c..e13cc3749da 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -21,8 +21,8 @@ import asyncio from asyncio import log -from asyncio import test_utils from asyncio import unix_events +from test.test_asyncio import utils as test_utils MOCK_ANY = mock.ANY diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index de6fe120612..fdba636f207 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -11,8 +11,8 @@ import _winapi import asyncio -from asyncio import test_utils from asyncio import windows_events +from test.test_asyncio import utils as test_utils class UpperProto(asyncio.Protocol): diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py index 952f95e5730..9fc38586ab0 100644 --- a/Lib/test/test_asyncio/test_windows_utils.py +++ b/Lib/test/test_asyncio/test_windows_utils.py @@ -1,10 +1,8 @@ """Tests for window_utils""" -import socket import sys import unittest import warnings -from unittest import mock if sys.platform != 'win32': raise unittest.SkipTest('Windows only') @@ -13,10 +11,7 @@ import _winapi from asyncio import windows_utils -try: - from test import support -except ImportError: - from asyncio import test_support as support +from test import support class PipeTests(unittest.TestCase): diff --git a/Lib/asyncio/test_utils.py b/Lib/test/test_asyncio/utils.py similarity index 98% rename from Lib/asyncio/test_utils.py rename to Lib/test/test_asyncio/utils.py index 231916970c7..560db9f562d 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -26,11 +26,11 @@ except ImportError: # pragma: no cover ssl = None -from . import base_events -from . import events -from . import futures -from . import tasks -from .log import logger +from asyncio import base_events +from asyncio import events +from asyncio import futures +from asyncio import tasks +from asyncio.log import logger from test import support diff --git a/Misc/NEWS.d/next/Library/2017-12-10-19-14-55.bpo-32273.5KKlCv.rst b/Misc/NEWS.d/next/Library/2017-12-10-19-14-55.bpo-32273.5KKlCv.rst new file mode 100644 index 00000000000..3bbec8f6e34 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-10-19-14-55.bpo-32273.5KKlCv.rst @@ -0,0 +1 @@ +Move asyncio.test_utils to test.test_asyncio. From webhook-mailer at python.org Mon Dec 11 10:07:47 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 11 Dec 2017 15:07:47 -0000 Subject: [Python-checkins] Add asyncio.get_running_loop() function. (#4782) Message-ID: https://github.com/python/cpython/commit/abae67ebc2897ca37df067f322d19e19d1ef6d88 commit: abae67ebc2897ca37df067f322d19e19d1ef6d88 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-11T10:07:44-05:00 summary: Add asyncio.get_running_loop() function. (#4782) files: A Misc/NEWS.d/next/Library/2017-12-10-12-30-13.bpo-32269.Q85pKj.rst M Doc/library/asyncio-eventloops.rst M Lib/asyncio/events.py M Lib/test/test_asyncio/test_events.py diff --git a/Doc/library/asyncio-eventloops.rst b/Doc/library/asyncio-eventloops.rst index 2097260e219..3051fde5b93 100644 --- a/Doc/library/asyncio-eventloops.rst +++ b/Doc/library/asyncio-eventloops.rst @@ -25,6 +25,13 @@ the execution of the process. Equivalent to calling ``get_event_loop_policy().new_event_loop()``. +.. function:: get_running_loop() + + Return the running event loop in the current OS thread. If there + is no running event loop a :exc:`RuntimeError` is raised. + + .. versionadded:: 3.7 + .. _asyncio-event-loops: diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 7db1ded8e8b..e425b06e42f 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -7,7 +7,8 @@ 'get_event_loop_policy', 'set_event_loop_policy', 'get_event_loop', 'set_event_loop', 'new_event_loop', 'get_child_watcher', 'set_child_watcher', - '_set_running_loop', '_get_running_loop', + '_set_running_loop', 'get_running_loop', + '_get_running_loop', ) import functools @@ -646,6 +647,17 @@ class _RunningLoop(threading.local): _running_loop = _RunningLoop() +def get_running_loop(): + """Return the running event loop. Raise a RuntimeError if there is none. + + This function is thread-specific. + """ + loop = _get_running_loop() + if loop is None: + raise RuntimeError('no running event loop') + return loop + + def _get_running_loop(): """Return the running event loop or None. diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 39d5bb54a9d..1315febe403 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2733,10 +2733,13 @@ def get_event_loop(self): try: asyncio.set_event_loop_policy(Policy()) loop = asyncio.new_event_loop() + with self.assertRaisesRegex(RuntimeError, 'no running'): + self.assertIs(asyncio.get_running_loop(), None) self.assertIs(asyncio._get_running_loop(), None) async def func(): self.assertIs(asyncio.get_event_loop(), loop) + self.assertIs(asyncio.get_running_loop(), loop) self.assertIs(asyncio._get_running_loop(), loop) loop.run_until_complete(func()) @@ -2745,6 +2748,9 @@ def get_event_loop(self): if loop is not None: loop.close() + with self.assertRaisesRegex(RuntimeError, 'no running'): + self.assertIs(asyncio.get_running_loop(), None) + self.assertIs(asyncio._get_running_loop(), None) diff --git a/Misc/NEWS.d/next/Library/2017-12-10-12-30-13.bpo-32269.Q85pKj.rst b/Misc/NEWS.d/next/Library/2017-12-10-12-30-13.bpo-32269.Q85pKj.rst new file mode 100644 index 00000000000..9fa12446de2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-10-12-30-13.bpo-32269.Q85pKj.rst @@ -0,0 +1 @@ +Add asyncio.get_running_loop() function. From webhook-mailer at python.org Mon Dec 11 10:35:56 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 11 Dec 2017 15:35:56 -0000 Subject: [Python-checkins] bpo-32258: Replace 'yield from' to 'await' in asyncio docs (#4779) Message-ID: https://github.com/python/cpython/commit/8874342cf332c3aa3d845155cc4b41b00c2d9e9d commit: 8874342cf332c3aa3d845155cc4b41b00c2d9e9d branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-11T17:35:49+02:00 summary: bpo-32258: Replace 'yield from' to 'await' in asyncio docs (#4779) * Replace 'yield from' to 'await' in asyncio docs * Fix docstrings files: M Doc/library/asyncio-dev.rst M Doc/library/asyncio-protocol.rst M Doc/library/asyncio-queue.rst M Doc/library/asyncio-stream.rst M Doc/library/asyncio-subprocess.rst M Doc/library/asyncio-task.rst M Lib/asyncio/coroutines.py M Lib/asyncio/futures.py M Lib/asyncio/locks.py diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst index b9735de2078..100fff561c5 100644 --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -81,12 +81,11 @@ is called. If you wait for a future, you should check early if the future was cancelled to avoid useless operations. Example:: - @coroutine - def slow_operation(fut): + async def slow_operation(fut): if fut.cancelled(): return # ... slow computation ... - yield from fut + await fut # ... The :func:`shield` function can also be used to ignore cancellation. @@ -99,7 +98,7 @@ Concurrency and multithreading An event loop runs in a thread and executes all callbacks and tasks in the same thread. While a task is running in the event loop, no other task is running in -the same thread. But when the task uses ``yield from``, the task is suspended +the same thread. But when the task uses ``await``, the task is suspended and the event loop executes the next task. To schedule a callback from a different thread, the @@ -192,8 +191,7 @@ Example with the bug:: import asyncio - @asyncio.coroutine - def test(): + async def test(): print("never scheduled") test() @@ -270,10 +268,9 @@ traceback where the task was created. Output in debug mode:: There are different options to fix this issue. The first option is to chain the coroutine in another coroutine and use classic try/except:: - @asyncio.coroutine - def handle_exception(): + async def handle_exception(): try: - yield from bug() + await bug() except Exception: print("exception consumed") @@ -300,7 +297,7 @@ Chain coroutines correctly -------------------------- When a coroutine function calls other coroutine functions and tasks, they -should be chained explicitly with ``yield from``. Otherwise, the execution is +should be chained explicitly with ``await``. Otherwise, the execution is not guaranteed to be sequential. Example with different bugs using :func:`asyncio.sleep` to simulate slow @@ -308,26 +305,22 @@ operations:: import asyncio - @asyncio.coroutine - def create(): - yield from asyncio.sleep(3.0) + async def create(): + await asyncio.sleep(3.0) print("(1) create file") - @asyncio.coroutine - def write(): - yield from asyncio.sleep(1.0) + async def write(): + await asyncio.sleep(1.0) print("(2) write into file") - @asyncio.coroutine - def close(): + async def close(): print("(3) close file") - @asyncio.coroutine - def test(): + async def test(): asyncio.ensure_future(create()) asyncio.ensure_future(write()) asyncio.ensure_future(close()) - yield from asyncio.sleep(2.0) + await asyncio.sleep(2.0) loop.stop() loop = asyncio.get_event_loop() @@ -359,24 +352,22 @@ The loop stopped before the ``create()`` finished, ``close()`` has been called before ``write()``, whereas coroutine functions were called in this order: ``create()``, ``write()``, ``close()``. -To fix the example, tasks must be marked with ``yield from``:: +To fix the example, tasks must be marked with ``await``:: - @asyncio.coroutine - def test(): - yield from asyncio.ensure_future(create()) - yield from asyncio.ensure_future(write()) - yield from asyncio.ensure_future(close()) - yield from asyncio.sleep(2.0) + async def test(): + await asyncio.ensure_future(create()) + await asyncio.ensure_future(write()) + await asyncio.ensure_future(close()) + await asyncio.sleep(2.0) loop.stop() Or without ``asyncio.ensure_future()``:: - @asyncio.coroutine - def test(): - yield from create() - yield from write() - yield from close() - yield from asyncio.sleep(2.0) + async def test(): + await create() + await write() + await close() + await asyncio.sleep(2.0) loop.stop() diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index af462009fa8..a4b0d594933 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -488,8 +488,9 @@ Coroutines can be scheduled in a protocol method using :func:`ensure_future`, but there is no guarantee made about the execution order. Protocols are not aware of coroutines created in protocol methods and so will not wait for them. -To have a reliable execution order, use :ref:`stream objects ` in a -coroutine with ``yield from``. For example, the :meth:`StreamWriter.drain` +To have a reliable execution order, +use :ref:`stream objects ` in a +coroutine with ``await``. For example, the :meth:`StreamWriter.drain` coroutine can be used to wait until the write buffer is flushed. @@ -589,7 +590,7 @@ received data and close the connection:: :meth:`Transport.close` can be called immediately after :meth:`WriteTransport.write` even if data are not sent yet on the socket: both -methods are asynchronous. ``yield from`` is not needed because these transport +methods are asynchronous. ``await`` is not needed because these transport methods are not coroutines. .. seealso:: diff --git a/Doc/library/asyncio-queue.rst b/Doc/library/asyncio-queue.rst index ea787550082..65497f29d89 100644 --- a/Doc/library/asyncio-queue.rst +++ b/Doc/library/asyncio-queue.rst @@ -24,7 +24,7 @@ Queue A queue, useful for coordinating producer and consumer coroutines. If *maxsize* is less than or equal to zero, the queue size is infinite. If - it is an integer greater than ``0``, then ``yield from put()`` will block + it is an integer greater than ``0``, then ``await put()`` will block when the queue reaches *maxsize*, until an item is removed by :meth:`get`. Unlike the standard library :mod:`queue`, you can reliably know this Queue's diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst index 78091d62a71..6d5cbbc5bd5 100644 --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -208,7 +208,7 @@ StreamWriter The intended use is to write:: w.write(data) - yield from w.drain() + await w.drain() When the size of the transport buffer reaches the high-water limit (the protocol is paused), block until the size of the buffer is drained down @@ -301,15 +301,14 @@ TCP echo client using the :func:`asyncio.open_connection` function:: import asyncio - @asyncio.coroutine - def tcp_echo_client(message, loop): - reader, writer = yield from asyncio.open_connection('127.0.0.1', 8888, - loop=loop) + async def tcp_echo_client(message, loop): + reader, writer = await asyncio.open_connection('127.0.0.1', 8888, + loop=loop) print('Send: %r' % message) writer.write(message.encode()) - data = yield from reader.read(100) + data = await reader.read(100) print('Received: %r' % data.decode()) print('Close the socket') @@ -335,16 +334,15 @@ TCP echo server using the :func:`asyncio.start_server` function:: import asyncio - @asyncio.coroutine - def handle_echo(reader, writer): - data = yield from reader.read(100) + async def handle_echo(reader, writer): + data = await reader.read(100) message = data.decode() addr = writer.get_extra_info('peername') print("Received %r from %r" % (message, addr)) print("Send: %r" % message) writer.write(data) - yield from writer.drain() + await writer.drain() print("Close the client socket") writer.close() @@ -387,13 +385,13 @@ Simple example querying HTTP headers of the URL passed on the command line:: connect = asyncio.open_connection(url.hostname, 443, ssl=True) else: connect = asyncio.open_connection(url.hostname, 80) - reader, writer = yield from connect + reader, writer = await connect query = ('HEAD {path} HTTP/1.0\r\n' 'Host: {hostname}\r\n' '\r\n').format(path=url.path or '/', hostname=url.hostname) writer.write(query.encode('latin-1')) while True: - line = yield from reader.readline() + line = await reader.readline() if not line: break line = line.decode('latin1').rstrip() @@ -428,19 +426,18 @@ Coroutine waiting until a socket receives data using the import asyncio from socket import socketpair - @asyncio.coroutine - def wait_for_data(loop): + async def wait_for_data(loop): # Create a pair of connected sockets rsock, wsock = socketpair() # Register the open socket to wait for data - reader, writer = yield from asyncio.open_connection(sock=rsock, loop=loop) + reader, writer = await asyncio.open_connection(sock=rsock, loop=loop) # Simulate the reception of data from the network loop.call_soon(wsock.send, 'abc'.encode()) # Wait for data - data = yield from reader.read(100) + data = await reader.read(100) # Got data, we are done: close the socket print("Received:", data.decode()) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst index 1c1d0be918d..280b7640037 100644 --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -347,21 +347,20 @@ wait for the subprocess exit. The subprocess is created by the def process_exited(self): self.exit_future.set_result(True) - @asyncio.coroutine - def get_date(loop): + async def get_date(loop): code = 'import datetime; print(datetime.datetime.now())' exit_future = asyncio.Future(loop=loop) # Create the subprocess controlled by the protocol DateProtocol, # redirect the standard output into a pipe - create = loop.subprocess_exec(lambda: DateProtocol(exit_future), - sys.executable, '-c', code, - stdin=None, stderr=None) - transport, protocol = yield from create + transport, protocol = await loop.subprocess_exec( + lambda: DateProtocol(exit_future), + sys.executable, '-c', code, + stdin=None, stderr=None) # Wait for the subprocess exit using the process_exited() method # of the protocol - yield from exit_future + await exit_future # Close the stdout pipe transport.close() @@ -398,16 +397,16 @@ function:: code = 'import datetime; print(datetime.datetime.now())' # Create the subprocess, redirect the standard output into a pipe - create = asyncio.create_subprocess_exec(sys.executable, '-c', code, - stdout=asyncio.subprocess.PIPE) - proc = yield from create + proc = await asyncio.create_subprocess_exec( + sys.executable, '-c', code, + stdout=asyncio.subprocess.PIPE) # Read one line of output - data = yield from proc.stdout.readline() + data = await proc.stdout.readline() line = data.decode('ascii').rstrip() # Wait for the subprocess exit - yield from proc.wait() + await proc.wait() return line if sys.platform == "win32": diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 3656f793deb..a8a0a8e85ef 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -515,7 +515,7 @@ Task functions Example:: for f in as_completed(fs): - result = yield from f # The 'yield from' may raise + result = await f # The 'await' may raise # Use result .. note:: @@ -630,11 +630,11 @@ Task functions The statement:: - res = yield from shield(something()) + res = await shield(something()) is exactly equivalent to the statement:: - res = yield from something() + res = await something() *except* that if the coroutine containing it is cancelled, the task running in ``something()`` is not cancelled. From the point of view of @@ -647,7 +647,7 @@ Task functions combine ``shield()`` with a try/except clause, as follows:: try: - res = yield from shield(something()) + res = await shield(something()) except CancelledError: res = None @@ -690,7 +690,7 @@ Task functions Usage:: - done, pending = yield from asyncio.wait(fs) + done, pending = await asyncio.wait(fs) .. note:: @@ -714,7 +714,7 @@ Task functions This function is a :ref:`coroutine `, usage:: - result = yield from asyncio.wait_for(fut, 60.0) + result = await asyncio.wait_for(fut, 60.0) .. versionchanged:: 3.4.3 If the wait is cancelled, the future *fut* is now also cancelled. diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index d7e6b4c1ccb..bca7fe3a537 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -19,8 +19,9 @@ def _is_debug_mode(): # If you set _DEBUG to true, @coroutine will wrap the resulting # generator objects in a CoroWrapper instance (defined below). That # instance will log a message when the generator is never iterated - # over, which may happen when you forget to use "yield from" with a - # coroutine call. Note that the value of the _DEBUG flag is taken + # over, which may happen when you forget to use "await" or "yield from" + # with a coroutine call. + # Note that the value of the _DEBUG flag is taken # when the decorator is used, so to be of any use it must be set # before you define your coroutines. A downside of using this feature # is that tracebacks show entries for the CoroWrapper.__next__ method diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index b805f99896d..d46a295197b 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -59,7 +59,8 @@ class Future: # The value must also be not-None, to enable a subclass to declare # that it is not compatible by setting this to None. # - It is set by __iter__() below so that Task._step() can tell - # the difference between `yield from Future()` (correct) vs. + # the difference between + # `await Future()` or`yield from Future()` (correct) vs. # `yield Future()` (incorrect). _asyncio_future_blocking = False @@ -236,7 +237,7 @@ def __iter__(self): if not self.done(): self._asyncio_future_blocking = True yield self # This tells Task to wait for completion. - assert self.done(), "yield from wasn't used with future" + assert self.done(), "await wasn't used with future" return self.result() # May raise too. __await__ = __iter__ # make compatible with 'await' expression diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 54f62585983..61938373509 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -23,6 +23,10 @@ class _ContextManager: with lock: + + Deprecated, use 'async with' statement: + async with lock: + """ def __init__(self, lock): @@ -64,6 +68,9 @@ def __iter__(self): # # finally: # lock.release() + # Deprecated, use 'async with' statement: + # async with lock: + # warnings.warn("'with (yield from lock)' is deprecated " "use 'async with lock' instead", DeprecationWarning, stacklevel=2) @@ -113,16 +120,16 @@ class Lock(_ContextManagerMixin): release() call resets the state to unlocked; first coroutine which is blocked in acquire() is being processed. - acquire() is a coroutine and should be called with 'yield from'. + acquire() is a coroutine and should be called with 'await'. - Locks also support the context management protocol. '(yield from lock)' - should be used as the context manager expression. + Locks also support the asynchronous context management protocol. + 'async with lock' statement should be used. Usage: lock = Lock() ... - yield from lock + await lock.acquire() try: ... finally: @@ -132,13 +139,13 @@ class Lock(_ContextManagerMixin): lock = Lock() ... - with (yield from lock): + async with lock: ... Lock objects can be tested for locking state: if not lock.locked(): - yield from lock + await lock.acquire() else: # lock is acquired ... From webhook-mailer at python.org Mon Dec 11 16:56:34 2017 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Mon, 11 Dec 2017 21:56:34 -0000 Subject: [Python-checkins] bpo-32227: functools.singledispatch supports registering via type annotations (#4733) Message-ID: https://github.com/python/cpython/commit/e56975351bc2c574c728f738e88effba7116279f commit: e56975351bc2c574c728f738e88effba7116279f branch: master author: ?ukasz Langa committer: GitHub date: 2017-12-11T13:56:31-08:00 summary: bpo-32227: functools.singledispatch supports registering via type annotations (#4733) files: A Misc/NEWS.d/next/Library/2017-12-05-13-25-15.bpo-32227.3vnWFS.rst M Doc/library/functools.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 28062c11890..a81e819103a 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -281,23 +281,34 @@ The :mod:`functools` module defines the following functions: ... print(arg) To add overloaded implementations to the function, use the :func:`register` - attribute of the generic function. It is a decorator, taking a type - parameter and decorating a function implementing the operation for that - type:: + attribute of the generic function. It is a decorator. For functions + annotated with types, the decorator will infer the type of the first + argument automatically:: - >>> @fun.register(int) - ... def _(arg, verbose=False): + >>> @fun.register + ... def _(arg: int, verbose=False): ... if verbose: ... print("Strength in numbers, eh?", end=" ") ... print(arg) ... - >>> @fun.register(list) - ... def _(arg, verbose=False): + >>> @fun.register + ... def _(arg: list, verbose=False): ... if verbose: ... print("Enumerate this:") ... for i, elem in enumerate(arg): ... print(i, elem) + For code which doesn't use type annotations, the appropriate type + argument can be passed explicitly to the decorator itself:: + + >>> @fun.register(complex) + ... def _(arg, verbose=False): + ... if verbose: + ... print("Better than complicated.", end=" ") + ... print(arg.real, arg.imag) + ... + + To enable registering lambdas and pre-existing functions, the :func:`register` attribute can be used in a functional form:: @@ -368,6 +379,9 @@ The :mod:`functools` module defines the following functions: .. versionadded:: 3.4 + .. versionchanged:: 3.7 + The :func:`register` attribute supports using type annotations. + .. function:: update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) diff --git a/Lib/functools.py b/Lib/functools.py index a51dddf8785..c8b79c2a7c2 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -793,7 +793,23 @@ def register(cls, func=None): """ nonlocal cache_token if func is None: - return lambda f: register(cls, f) + if isinstance(cls, type): + return lambda f: register(cls, f) + ann = getattr(cls, '__annotations__', {}) + if not ann: + raise TypeError( + f"Invalid first argument to `register()`: {cls!r}. " + f"Use either `@register(some_class)` or plain `@register` " + f"on an annotated function." + ) + func = cls + + # only import typing if annotation parsing is necessary + from typing import get_type_hints + argname, cls = next(iter(get_type_hints(func).items())) + assert isinstance(cls, type), ( + f"Invalid annotation for {argname!r}. {cls!r} is not a class." + ) registry[cls] = func if cache_token is None and hasattr(cls, '__abstractmethods__'): cache_token = get_cache_token() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 68e94e7ae17..35ec2e2f481 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -10,6 +10,7 @@ from test import support import threading import time +import typing import unittest import unittest.mock from weakref import proxy @@ -2119,6 +2120,73 @@ class X: g._clear_cache() self.assertEqual(len(td), 0) + def test_annotations(self): + @functools.singledispatch + def i(arg): + return "base" + @i.register + def _(arg: collections.abc.Mapping): + return "mapping" + @i.register + def _(arg: "collections.abc.Sequence"): + return "sequence" + self.assertEqual(i(None), "base") + self.assertEqual(i({"a": 1}), "mapping") + self.assertEqual(i([1, 2, 3]), "sequence") + self.assertEqual(i((1, 2, 3)), "sequence") + self.assertEqual(i("str"), "sequence") + + # Registering classes as callables doesn't work with annotations, + # you need to pass the type explicitly. + @i.register(str) + class _: + def __init__(self, arg): + self.arg = arg + + def __eq__(self, other): + return self.arg == other + self.assertEqual(i("str"), "str") + + def test_invalid_registrations(self): + msg_prefix = "Invalid first argument to `register()`: " + msg_suffix = ( + ". Use either `@register(some_class)` or plain `@register` on an " + "annotated function." + ) + @functools.singledispatch + def i(arg): + return "base" + with self.assertRaises(TypeError) as exc: + @i.register(42) + def _(arg): + return "I annotated with a non-type" + self.assertTrue(str(exc.exception).startswith(msg_prefix + "42")) + self.assertTrue(str(exc.exception).endswith(msg_suffix)) + with self.assertRaises(TypeError) as exc: + @i.register + def _(arg): + return "I forgot to annotate" + self.assertTrue(str(exc.exception).startswith(msg_prefix + + "._" + )) + self.assertTrue(str(exc.exception).endswith(msg_suffix)) + + # FIXME: The following will only work after PEP 560 is implemented. + return + + with self.assertRaises(TypeError) as exc: + @i.register + def _(arg: typing.Iterable[str]): + # At runtime, dispatching on generics is impossible. + # When registering implementations with singledispatch, avoid + # types from `typing`. Instead, annotate with regular types + # or ABCs. + return "I annotated with a generic collection" + self.assertTrue(str(exc.exception).startswith(msg_prefix + + "._" + )) + self.assertTrue(str(exc.exception).endswith(msg_suffix)) + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-12-05-13-25-15.bpo-32227.3vnWFS.rst b/Misc/NEWS.d/next/Library/2017-12-05-13-25-15.bpo-32227.3vnWFS.rst new file mode 100644 index 00000000000..4dbc7ba907b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-05-13-25-15.bpo-32227.3vnWFS.rst @@ -0,0 +1,2 @@ +``functools.singledispatch`` now supports registering implementations using +type annotations. From lp_benchmark_robot at intel.com Mon Dec 11 20:21:01 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Mon, 11 Dec 2017 17:21:01 -0800 Subject: [Python-checkins] [2 down, 1 up, 62 flat] Results for Python (master branch) 2017-12-11 Message-ID: Results for project python/master, build date: 2017-12-11 03:03:18-08:00. - commit: 19d0d54 - previous commit: 11cc289 - revision date: 2017-12-10 19:52:53-05:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.887% | -0.564% | +4.463% | +8.705% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.485% | +1.651% | +23.228% | +9.929% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.702% | +0.966% | +23.524% | +9.316% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.895% | +0.022% | +21.430% | +12.219% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.195% | +0.210% | +7.639% | +10.884% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.974% | -1.734% | +9.476% | +13.988% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.797% | +0.359% | +7.346% | +11.142% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.441% | -0.782% | -0.409% | +8.760% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 4.015% | -1.164% | +8.054% | +20.027% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.348% | +2.379% | +12.898% | +6.183% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 2.703% | -1.636% | +2.695% | +8.703% | +-----+------------------------+--------+------------+------------+------------+ | :-( | fannkuch| 0.495% | -2.070% | +3.591% | +7.157% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.049% | -0.865% | +1.668% | +8.050% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.259% | -0.680% | +12.961% | +9.926% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.587% | -0.089% | +9.391% | +9.940% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.559% | -0.397% | +4.967% | +13.109% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.481% | -0.779% | +9.597% | +13.410% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.252% | -1.692% | +7.059% | +10.652% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.095% | -0.737% | +2.655% | +9.567% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 2.321% | +0.301% | +0.852% | +11.835% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.615% | +0.791% | +6.741% | +12.919% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 4.113% | -1.169% | +46.117% | +15.817% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.646% | +0.840% | +7.923% | +15.097% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.767% | -0.531% | +16.219% | +13.636% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 1.760% | -0.102% | +5.865% | +12.236% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 2.239% | -0.479% | +3.601% | +6.005% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.592% | +0.219% | -1.330% | -0.311% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.754% | +0.641% | +5.289% | +7.115% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.408% | +1.601% | +7.631% | +7.631% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 4.524% | +0.018% | +0.694% | +21.595% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.327% | +1.280% | +1.561% | +19.875% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.844% | +2.233% | +2.247% | +22.154% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.094% | -0.519% | +9.348% | +12.965% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.050% | -0.315% | +0.043% | +10.287% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.133% | -0.343% | +10.181% | +5.310% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.114% | -0.576% | +1.305% | +5.436% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.271% | +0.314% | +9.898% | +14.462% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.390% | +1.874% | +4.640% | +7.515% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.421% | +0.529% | -0.937% | +11.283% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.575% | +2.125% | -3.284% | +4.821% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.041% | +0.284% | +4.256% | +8.309% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.890% | +0.320% | +7.865% | +16.219% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.426% | +1.307% | -1.947% | +4.176% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.893% | +0.323% | +27.476% | +8.671% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.096% | -1.391% | +3.161% | +8.228% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.063% | -2.043% | +12.797% | +11.055% | +-----+------------------------+--------+------------+------------+------------+ | :-) | scimark_sparse_mat_mult| 0.343% | +1.877% | -2.917% | +0.756% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.539% | +1.662% | +4.886% | +4.008% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.129% | +0.149% | +6.849% | +6.758% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.227% | +0.150% | +6.719% | +3.126% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 5.314% | +1.907% | +19.782% | +7.355% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 1.945% | +0.405% | +11.522% | +8.254% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.694% | +0.651% | +9.462% | +6.128% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.005% | +0.334% | +11.570% | +7.886% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.465% | -0.931% | +9.861% | +10.040% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.280% | -1.371% | +19.040% | +13.322% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.058% | +0.123% | +6.060% | +4.597% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.871% | +0.125% | +1.562% | +3.139% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 6.050% | +0.320% | +4.724% | +22.156% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 2.054% | +0.537% | -0.495% | +15.481% | +-----+------------------------+--------+------------+------------+------------+ | :-( | unpickle_pure_python| 3.009% | -5.595% | +2.840% | +10.576% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.777% | +0.208% | +5.902% | +7.989% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.083% | +0.318% | +3.618% | +8.199% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.979% | -0.302% | -7.420% | +12.564% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.583% | -0.570% | +6.829% | +9.055% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/2-down-1-up-62-flat-results-for-python-master-branch-2017-12-11 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Mon Dec 11 22:59:11 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 12 Dec 2017 03:59:11 -0000 Subject: [Python-checkins] Fix idlelib comment typos reported by Mike on pull request 4803. (#4807) Message-ID: https://github.com/python/cpython/commit/e570211406f9bfbe16eff8d10e614d90497e08df commit: e570211406f9bfbe16eff8d10e614d90497e08df branch: master author: Terry Jan Reedy committer: GitHub date: 2017-12-11T22:59:08-05:00 summary: Fix idlelib comment typos reported by Mike on pull request 4803. (#4807) files: M Lib/idlelib/autocomplete_w.py M Lib/idlelib/idle_test/test_query.py M Lib/idlelib/idle_test/test_search.py diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index 7c3138f4040..12113f95e63 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -246,7 +246,7 @@ def winconfig_event(self, event): acw.wm_geometry("+%d+%d" % (new_x, new_y)) if platform.system().startswith('Windows'): - # See issue 15786. When on windows platform, Tk will misbehaive + # See issue 15786. When on windows platform, Tk will misbehave # to call winconfig_event multiple times, we need to prevent this, # otherwise mouse button double click will not be able to used. acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index 1210afe70df..953f24f0a5a 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -162,7 +162,7 @@ def test_file_replaces_path(self): # Path is widget entry, either '' or something. # Func return is file dialog return, either '' or something. # Func return should override widget entry. - # We need all 4 combination to test all (most) code paths. + # We need all 4 combinations to test all (most) code paths. for path, func, result in ( ('', lambda a,b,c:'', ''), ('', lambda a,b,c: __file__, __file__), diff --git a/Lib/idlelib/idle_test/test_search.py b/Lib/idlelib/idle_test/test_search.py index 80fa93adf51..3ab72951efe 100644 --- a/Lib/idlelib/idle_test/test_search.py +++ b/Lib/idlelib/idle_test/test_search.py @@ -1,7 +1,7 @@ """Test SearchDialog class in idlelib.search.py""" # Does not currently test the event handler wrappers. -# A usage test should simulate clicks and check hilighting. +# A usage test should simulate clicks and check highlighting. # Tests need to be coordinated with SearchDialogBase tests # to avoid duplication. From webhook-mailer at python.org Mon Dec 11 23:29:38 2017 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 12 Dec 2017 04:29:38 -0000 Subject: [Python-checkins] Fix idlelib comment typos reported by Mike on pull request 4803. (GH-4807) (#4809) Message-ID: https://github.com/python/cpython/commit/82adaf5ffe425f3d3360e972df03ff15584b4035 commit: 82adaf5ffe425f3d3360e972df03ff15584b4035 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2017-12-11T23:29:34-05:00 summary: Fix idlelib comment typos reported by Mike on pull request 4803. (GH-4807) (#4809) (cherry picked from commit e570211406f9bfbe16eff8d10e614d90497e08df) files: M Lib/idlelib/autocomplete_w.py M Lib/idlelib/idle_test/test_query.py M Lib/idlelib/idle_test/test_search.py diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index 7c3138f4040..12113f95e63 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -246,7 +246,7 @@ def winconfig_event(self, event): acw.wm_geometry("+%d+%d" % (new_x, new_y)) if platform.system().startswith('Windows'): - # See issue 15786. When on windows platform, Tk will misbehaive + # See issue 15786. When on windows platform, Tk will misbehave # to call winconfig_event multiple times, we need to prevent this, # otherwise mouse button double click will not be able to used. acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index 1210afe70df..953f24f0a5a 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -162,7 +162,7 @@ def test_file_replaces_path(self): # Path is widget entry, either '' or something. # Func return is file dialog return, either '' or something. # Func return should override widget entry. - # We need all 4 combination to test all (most) code paths. + # We need all 4 combinations to test all (most) code paths. for path, func, result in ( ('', lambda a,b,c:'', ''), ('', lambda a,b,c: __file__, __file__), diff --git a/Lib/idlelib/idle_test/test_search.py b/Lib/idlelib/idle_test/test_search.py index 80fa93adf51..3ab72951efe 100644 --- a/Lib/idlelib/idle_test/test_search.py +++ b/Lib/idlelib/idle_test/test_search.py @@ -1,7 +1,7 @@ """Test SearchDialog class in idlelib.search.py""" # Does not currently test the event handler wrappers. -# A usage test should simulate clicks and check hilighting. +# A usage test should simulate clicks and check highlighting. # Tests need to be coordinated with SearchDialogBase tests # to avoid duplication. From webhook-mailer at python.org Tue Dec 12 02:59:33 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Tue, 12 Dec 2017 07:59:33 -0000 Subject: [Python-checkins] Fix small typo in tupleobject.h (#4801) Message-ID: https://github.com/python/cpython/commit/e0720cd9e44d43587e6b6c91fd21d0bb0345ccb9 commit: e0720cd9e44d43587e6b6c91fd21d0bb0345ccb9 branch: master author: Chris committer: Andrew Svetlov date: 2017-12-12T09:59:30+02:00 summary: Fix small typo in tupleobject.h (#4801) files: M Include/tupleobject.h diff --git a/Include/tupleobject.h b/Include/tupleobject.h index 98c26220ea0..72a7d8d5850 100644 --- a/Include/tupleobject.h +++ b/Include/tupleobject.h @@ -10,7 +10,7 @@ extern "C" { /* Another generally useful object type is a tuple of object pointers. For Python, this is an immutable type. C code can change the tuple items -(but not their number), and even use tuples are general-purpose arrays of +(but not their number), and even use tuples as general-purpose arrays of object references, but in general only brand new tuples should be mutated, not ones that might already have been exposed to Python code. From solipsis at pitrou.net Tue Dec 12 04:08:57 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 12 Dec 2017 09:08:57 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171212090857.13232.4FEBDFFCE6B9449E@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogwuMufx', '--timeout', '7200'] From webhook-mailer at python.org Tue Dec 12 04:57:10 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 09:57:10 -0000 Subject: [Python-checkins] bpo-32255: Always quote a single empty field when write into a CSV file. (#4769) Message-ID: https://github.com/python/cpython/commit/2001900b0c02a397d8cf1d776a7cc7fcb2a463e3 commit: 2001900b0c02a397d8cf1d776a7cc7fcb2a463e3 branch: master author: Licht Takeuchi committer: Serhiy Storchaka date: 2017-12-12T11:57:06+02:00 summary: bpo-32255: Always quote a single empty field when write into a CSV file. (#4769) This allows to distinguish an empty row from a row consisting of a single empty field. files: A Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst M Lib/test/test_csv.py M Misc/ACKS M Modules/_csv.c diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 03ab1840dd0..fe248019a0f 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -207,10 +207,29 @@ def write(self, buf): with TemporaryFile("w+", newline='') as fileobj: writer = csv.writer(fileobj) self.assertRaises(TypeError, writer.writerows, None) - writer.writerows([['a','b'],['c','d']]) + writer.writerows([['a', 'b'], ['c', 'd']]) fileobj.seek(0) self.assertEqual(fileobj.read(), "a,b\r\nc,d\r\n") + def test_writerows_with_none(self): + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([['a', None], [None, 'd']]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), "a,\r\n,d\r\n") + + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([[None], ['a']]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), '""\r\na\r\n') + + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([['a'], [None]]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), 'a\r\n""\r\n') + @support.cpython_only def test_writerows_legacy_strings(self): import _testcapi diff --git a/Misc/ACKS b/Misc/ACKS index 54d8d62b633..8303ce80050 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1554,6 +1554,7 @@ Joel Taddei Arfrever Frehtes Taifersar Arahesis Hideaki Takahashi Takase Arihiro +Licht Takeuchi Indra Talip Neil Tallim Geoff Talvola diff --git a/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst b/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst new file mode 100644 index 00000000000..dafee67bdd0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst @@ -0,0 +1,3 @@ +A single empty field is now always quoted when written into a CSV file. +This allows to distinguish an empty row from a row consisting of a single empty field. +Patch by Licht Takeuchi. diff --git a/Modules/_csv.c b/Modules/_csv.c index 5314ef6edc4..e616151bae6 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -1238,7 +1238,7 @@ csv_writerow(WriterObj *self, PyObject *seq) if (PyErr_Occurred()) return NULL; - if (self->num_fields > 0 && self->rec_size == 0) { + if (self->num_fields > 0 && self->rec_len == 0) { if (dialect->quoting == QUOTE_NONE) { PyErr_Format(_csvstate_global->error_obj, "single empty field record must be quoted"); From webhook-mailer at python.org Tue Dec 12 05:22:38 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 12 Dec 2017 10:22:38 -0000 Subject: [Python-checkins] bpo-31942: Document optional support of start and stop attributes in Sequence.index method (#4277) Message-ID: https://github.com/python/cpython/commit/5ce0a2a100909104836f53a2c8823006ec46f8ad commit: 5ce0a2a100909104836f53a2c8823006ec46f8ad branch: master author: Nitish Chandra committer: Victor Stinner date: 2017-12-12T11:22:30+01:00 summary: bpo-31942: Document optional support of start and stop attributes in Sequence.index method (#4277) files: M Doc/library/stdtypes.rst M Lib/_collections_abc.py diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 0bcafd33b20..de2fb27c2d7 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -973,9 +973,9 @@ Notes: (8) ``index`` raises :exc:`ValueError` when *x* is not found in *s*. - When supported, the additional arguments to the index method allow - efficient searching of subsections of the sequence. Passing the extra - arguments is roughly equivalent to using ``s[i:j].index(x)``, only + Not all implementations support passing the additional arguments *i* and *j*. + These arguments allow efficient searching of subsections of the sequence. Passing + the extra arguments is roughly equivalent to using ``s[i:j].index(x)``, only without copying any data and with the returned index being relative to the start of the sequence rather than the start of the slice. diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index e89e84bc081..a5c7bfcda1d 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -899,6 +899,9 @@ def __reversed__(self): 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. + + Supporting start and stop arguments is optional, but + recommended. ''' if start is not None and start < 0: start = max(len(self) + start, 0) From webhook-mailer at python.org Tue Dec 12 05:56:44 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 10:56:44 -0000 Subject: [Python-checkins] bpo-32255: Always quote a single empty field when write into a CSV file. (GH-4769) (#4810) Message-ID: https://github.com/python/cpython/commit/ce5a3cd9b15c9379753aefabd696bff11495cbbb commit: ce5a3cd9b15c9379753aefabd696bff11495cbbb branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-12T12:56:40+02:00 summary: bpo-32255: Always quote a single empty field when write into a CSV file. (GH-4769) (#4810) This allows to distinguish an empty row from a row consisting of a single empty field. (cherry picked from commit 2001900b0c02a397d8cf1d776a7cc7fcb2a463e3) files: A Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst M Lib/test/test_csv.py M Misc/ACKS M Modules/_csv.c diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 03ab1840dd0..fe248019a0f 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -207,10 +207,29 @@ def write(self, buf): with TemporaryFile("w+", newline='') as fileobj: writer = csv.writer(fileobj) self.assertRaises(TypeError, writer.writerows, None) - writer.writerows([['a','b'],['c','d']]) + writer.writerows([['a', 'b'], ['c', 'd']]) fileobj.seek(0) self.assertEqual(fileobj.read(), "a,b\r\nc,d\r\n") + def test_writerows_with_none(self): + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([['a', None], [None, 'd']]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), "a,\r\n,d\r\n") + + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([[None], ['a']]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), '""\r\na\r\n') + + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([['a'], [None]]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), 'a\r\n""\r\n') + @support.cpython_only def test_writerows_legacy_strings(self): import _testcapi diff --git a/Misc/ACKS b/Misc/ACKS index 5f21c4bce07..0a0823cf624 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1525,6 +1525,7 @@ Joel Taddei Arfrever Frehtes Taifersar Arahesis Hideaki Takahashi Takase Arihiro +Licht Takeuchi Indra Talip Neil Tallim Geoff Talvola diff --git a/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst b/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst new file mode 100644 index 00000000000..dafee67bdd0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-12-07-29-06.bpo-32255.2bfNmM.rst @@ -0,0 +1,3 @@ +A single empty field is now always quoted when written into a CSV file. +This allows to distinguish an empty row from a row consisting of a single empty field. +Patch by Licht Takeuchi. diff --git a/Modules/_csv.c b/Modules/_csv.c index 7a78541bf2d..c61eae5341a 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -1245,7 +1245,7 @@ csv_writerow(WriterObj *self, PyObject *seq) if (PyErr_Occurred()) return NULL; - if (self->num_fields > 0 && self->rec_size == 0) { + if (self->num_fields > 0 && self->rec_len == 0) { if (dialect->quoting == QUOTE_NONE) { PyErr_Format(_csvstate_global->error_obj, "single empty field record must be quoted"); From webhook-mailer at python.org Tue Dec 12 05:58:29 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 12 Dec 2017 10:58:29 -0000 Subject: [Python-checkins] bpo-31942: Document optional support of start and stop attributes in Sequence.index method (GH-4277) (#4811) Message-ID: https://github.com/python/cpython/commit/78cd00b799be36a35c9f5cc99ce3bcef31112a5f commit: 78cd00b799be36a35c9f5cc99ce3bcef31112a5f branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Victor Stinner date: 2017-12-12T11:58:26+01:00 summary: bpo-31942: Document optional support of start and stop attributes in Sequence.index method (GH-4277) (#4811) (cherry picked from commit 5ce0a2a100909104836f53a2c8823006ec46f8ad) files: M Doc/library/stdtypes.rst M Lib/_collections_abc.py diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 75e97b9d8f5..196a4c00056 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -973,9 +973,9 @@ Notes: (8) ``index`` raises :exc:`ValueError` when *x* is not found in *s*. - When supported, the additional arguments to the index method allow - efficient searching of subsections of the sequence. Passing the extra - arguments is roughly equivalent to using ``s[i:j].index(x)``, only + Not all implementations support passing the additional arguments *i* and *j*. + These arguments allow efficient searching of subsections of the sequence. Passing + the extra arguments is roughly equivalent to using ``s[i:j].index(x)``, only without copying any data and with the returned index being relative to the start of the sequence rather than the start of the slice. diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index 005d8845724..aafd43046a0 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -899,6 +899,9 @@ def __reversed__(self): 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. + + Supporting start and stop arguments is optional, but + recommended. ''' if start is not None and start < 0: start = max(len(self) + start, 0) From webhook-mailer at python.org Tue Dec 12 06:55:06 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 11:55:06 -0000 Subject: [Python-checkins] bpo-32241: Add the const qualifire to declarations of umodifiable strings. (#4748) Message-ID: https://github.com/python/cpython/commit/4ae06c5337e01bdde28bce57b6b9166ad50947e3 commit: 4ae06c5337e01bdde28bce57b6b9166ad50947e3 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-12T13:55:04+02:00 summary: bpo-32241: Add the const qualifire to declarations of umodifiable strings. (#4748) files: A Misc/NEWS.d/next/C API/2017-12-07-15-58-15.bpo-32241.LbyQt6.rst M Doc/c-api/init.rst M Include/pylifecycle.h M Modules/getaddrinfo.c M Modules/getpath.c M Modules/main.c M Objects/obmalloc.c M PC/getpathp.c M Python/bootstrap_hash.c M Python/dynamic_annotations.c M Python/frozenmain.c M Python/pathconfig.c M Python/pylifecycle.c M Python/sysmodule.c M Python/thread.c diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index a3113a390fd..4ee61e8a1cf 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -338,7 +338,7 @@ Process-wide parameters .. versionadded:: 3.4 -.. c:function:: void Py_SetProgramName(wchar_t *name) +.. c:function:: void Py_SetProgramName(const wchar_t *name) .. index:: single: Py_Initialize() @@ -605,7 +605,7 @@ Process-wide parameters .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. -.. c:function:: void Py_SetPythonHome(wchar_t *home) +.. c:function:: void Py_SetPythonHome(const wchar_t *home) Set the default "home" directory, that is, the location of the standard Python libraries. See :envvar:`PYTHONHOME` for the meaning of the diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index bda51f84c3c..542306004d2 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -37,10 +37,10 @@ typedef struct { #endif -PyAPI_FUNC(void) Py_SetProgramName(wchar_t *); +PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); -PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *); +PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void); #ifndef Py_LIMITED_API diff --git a/Misc/NEWS.d/next/C API/2017-12-07-15-58-15.bpo-32241.LbyQt6.rst b/Misc/NEWS.d/next/C API/2017-12-07-15-58-15.bpo-32241.LbyQt6.rst new file mode 100644 index 00000000000..71fa8baa807 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2017-12-07-15-58-15.bpo-32241.LbyQt6.rst @@ -0,0 +1,2 @@ +:c:func:`Py_SetProgramName` and :c:func:`Py_SetPythonHome` now take the +``const wchar *`` arguments instead of ``wchar *``. diff --git a/Modules/getaddrinfo.c b/Modules/getaddrinfo.c index 06e87bfc8ce..5aaa6e7c814 100644 --- a/Modules/getaddrinfo.c +++ b/Modules/getaddrinfo.c @@ -251,7 +251,7 @@ getaddrinfo(const char*hostname, const char*servname, if (firsttime) { /* translator hack */ { - char *q = getenv("GAI"); + const char *q = getenv("GAI"); if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) translate = YES; } diff --git a/Modules/getpath.c b/Modules/getpath.c index fc2b5442ce2..11babf0a00b 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -910,7 +910,7 @@ calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) { size_t len; - char *path = getenv("PATH"); + const char *path = getenv("PATH"); if (path) { calculate->path_env = Py_DecodeLocale(path, &len); if (!calculate->path_env) { diff --git a/Modules/main.c b/Modules/main.c index e536492379d..68ee616da62 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -154,10 +154,10 @@ pymain_usage(int error, const wchar_t* program) } -static char* +static const char* pymain_get_env_var(const char *name) { - char *var = Py_GETENV(name); + const char *var = Py_GETENV(name); if (var && var[0] != '\0') { return var; } @@ -170,7 +170,7 @@ pymain_get_env_var(const char *name) static void pymain_run_startup(PyCompilerFlags *cf) { - char *startup = pymain_get_env_var("PYTHONSTARTUP"); + const char *startup = pymain_get_env_var("PYTHONSTARTUP"); if (startup == NULL) { return; } @@ -542,7 +542,7 @@ pymain_run_main_from_importer(_PyMain *pymain) static wchar_t* -pymain_wstrdup(_PyMain *pymain, wchar_t *str) +pymain_wstrdup(_PyMain *pymain, const wchar_t *str) { wchar_t *str2 = _PyMem_RawWcsdup(str); if (str2 == NULL) { @@ -554,7 +554,7 @@ pymain_wstrdup(_PyMain *pymain, wchar_t *str) static int -pymain_optlist_append(_PyMain *pymain, _Py_OptList *list, wchar_t *str) +pymain_optlist_append(_PyMain *pymain, _Py_OptList *list, const wchar_t *str) { wchar_t *str2 = pymain_wstrdup(pymain, str); if (str2 == NULL) { @@ -802,7 +802,7 @@ pymain_warnings_envvar(_PyMain *pymain) } #ifdef MS_WINDOWS - wchar_t *wp; + const wchar_t *wp; if ((wp = _wgetenv(L"PYTHONWARNINGS")) && *wp != L'\0') { wchar_t *warning, *context = NULL; @@ -824,7 +824,7 @@ pymain_warnings_envvar(_PyMain *pymain) PyMem_RawFree(buf); } #else - char *p = pymain_get_env_var("PYTHONWARNINGS"); + const char *p = pymain_get_env_var("PYTHONWARNINGS"); if (p != NULL) { char *buf, *oldloc; @@ -909,7 +909,7 @@ config_get_program_name(_PyMainInterpreterConfig *config) assert(config->program_name == NULL); /* If Py_SetProgramName() was called, use its value */ - wchar_t *program_name = _Py_path_config.program_name; + const wchar_t *program_name = _Py_path_config.program_name; if (program_name != NULL) { config->program_name = _PyMem_RawWcsdup(program_name); if (config->program_name == NULL) { @@ -927,7 +927,7 @@ config_get_program_name(_PyMainInterpreterConfig *config) so the actual executable path is passed in an environment variable. See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ - char *p = pymain_get_env_var("PYTHONEXECUTABLE"); + const char *p = pymain_get_env_var("PYTHONEXECUTABLE"); if (p != NULL) { size_t len; wchar_t* program_name = Py_DecodeLocale(p, &len); @@ -939,7 +939,7 @@ config_get_program_name(_PyMainInterpreterConfig *config) } #ifdef WITH_NEXT_FRAMEWORK else { - char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__"); + const char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__"); if (pyvenv_launcher && *pyvenv_launcher) { /* Used by Mac/Tools/pythonw.c to forward * the argv0 of the stub executable @@ -1289,7 +1289,7 @@ pymain_parse_cmdline(_PyMain *pymain) } -static wchar_t* +static const wchar_t* pymain_get_xoption(_PyMain *pymain, wchar_t *name) { _Py_OptList *list = &pymain->cmdline.xoptions; @@ -1312,11 +1312,11 @@ pymain_get_xoption(_PyMain *pymain, wchar_t *name) static int -pymain_str_to_int(char *str, int *result) +pymain_str_to_int(const char *str, int *result) { errno = 0; - char *endptr = str; - long value = strtol(str, &endptr, 10); + const char *endptr = str; + long value = strtol(str, (char **)&endptr, 10); if (*endptr != '\0' || errno == ERANGE) { return -1; } @@ -1330,11 +1330,11 @@ pymain_str_to_int(char *str, int *result) static int -pymain_wstr_to_int(wchar_t *wstr, int *result) +pymain_wstr_to_int(const wchar_t *wstr, int *result) { errno = 0; - wchar_t *endptr = wstr; - long value = wcstol(wstr, &endptr, 10); + const wchar_t *endptr = wstr; + long value = wcstol(wstr, (wchar_t **)&endptr, 10); if (*endptr != '\0' || errno == ERANGE) { return -1; } @@ -1353,7 +1353,7 @@ pymain_init_tracemalloc(_PyMain *pymain) int nframe; int valid; - char *env = pymain_get_env_var("PYTHONTRACEMALLOC"); + const char *env = pymain_get_env_var("PYTHONTRACEMALLOC"); if (env) { if (!pymain_str_to_int(env, &nframe)) { valid = (nframe >= 1); @@ -1369,9 +1369,9 @@ pymain_init_tracemalloc(_PyMain *pymain) pymain->core_config.tracemalloc = nframe; } - wchar_t *xoption = pymain_get_xoption(pymain, L"tracemalloc"); + const wchar_t *xoption = pymain_get_xoption(pymain, L"tracemalloc"); if (xoption) { - wchar_t *sep = wcschr(xoption, L'='); + const wchar_t *sep = wcschr(xoption, L'='); if (sep) { if (!pymain_wstr_to_int(sep + 1, &nframe)) { valid = (nframe >= 1); @@ -1398,7 +1398,7 @@ pymain_init_tracemalloc(_PyMain *pymain) static void pymain_set_flag_from_env(int *flag, const char *name) { - char *var = pymain_get_env_var(name); + const char *var = pymain_get_env_var(name); if (!var) { return; } @@ -1449,7 +1449,7 @@ config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name) } #ifdef MS_WINDOWS - wchar_t *var = _wgetenv(wname); + const wchar_t *var = _wgetenv(wname); if (!var || var[0] == '\0') { *dest = NULL; return 0; @@ -1462,7 +1462,7 @@ config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name) *dest = copy; #else - char *var = getenv(name); + const char *var = getenv(name); if (!var || var[0] == '\0') { *dest = NULL; return 0; diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index c065541458b..0b8816cc54f 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1167,7 +1167,7 @@ new_arena(void) static int debug_stats = -1; if (debug_stats == -1) { - char *opt = Py_GETENV("PYTHONMALLOCSTATS"); + const char *opt = Py_GETENV("PYTHONMALLOCSTATS"); debug_stats = (opt != NULL && *opt != '\0'); } if (debug_stats) diff --git a/PC/getpathp.c b/PC/getpathp.c index 08ed8ccc83f..e142e365052 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -118,8 +118,8 @@ #endif typedef struct { - wchar_t *path_env; /* PATH environment variable */ - wchar_t *home; /* PYTHONHOME environment variable */ + const wchar_t *path_env; /* PATH environment variable */ + const wchar_t *home; /* PYTHONHOME environment variable */ /* Registry key "Software\Python\PythonCore\PythonPath" */ wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */ @@ -191,7 +191,7 @@ change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext) static int -exists(wchar_t *filename) +exists(const wchar_t *filename) { return GetFileAttributesW(filename) != 0xFFFFFFFF; } @@ -286,7 +286,7 @@ gotlandmark(wchar_t *prefix, const wchar_t *landmark) /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. assumption provided by only caller, calculate_path_impl() */ static int -search_for_prefix(wchar_t *prefix, wchar_t *argv0_path, const wchar_t *landmark) +search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *landmark) { /* Search from argv0_path, until landmark is found */ wcscpy_s(prefix, MAXPATHLEN + 1, argv0_path); @@ -523,9 +523,9 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); } else if (calculate->path_env) { - wchar_t *path = calculate->path_env; + const wchar_t *path = calculate->path_env; while (1) { - wchar_t *delim = wcschr(path, DELIM); + const wchar_t *delim = wcschr(path, DELIM); if (delim) { size_t len = delim - path; @@ -845,7 +845,7 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, /* Calculate size of return buffer */ size_t bufsz = 0; if (calculate->home != NULL) { - wchar_t *p; + const wchar_t *p; bufsz = 1; for (p = PYTHONPATH; *p; p++) { if (*p == DELIM) { @@ -922,8 +922,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, *buf++ = DELIM; } } else { - wchar_t *p = PYTHONPATH; - wchar_t *q; + const wchar_t *p = PYTHONPATH; + const wchar_t *q; size_t n; for (;;) { q = wcschr(p, DELIM); @@ -967,10 +967,10 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, */ if (prefix[0] == L'\0') { wchar_t lookBuf[MAXPATHLEN+1]; - wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */ + const wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */ while (1) { Py_ssize_t nchars; - wchar_t *lookEnd = look; + const wchar_t *lookEnd = look; /* 'look' will end up one character before the start of the path in question - even if this is one character before the start of the buffer diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 610541d810b..2762f4656e2 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -533,16 +533,16 @@ _PyOS_URandomNonblock(void *buffer, Py_ssize_t size) return pyurandom(buffer, size, 0, 1); } -int Py_ReadHashSeed(char *seed_text, +int Py_ReadHashSeed(const char *seed_text, int *use_hash_seed, unsigned long *hash_seed) { Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc)); /* Convert a text seed to a numeric one */ if (seed_text && *seed_text != '\0' && strcmp(seed_text, "random") != 0) { - char *endptr = seed_text; + const char *endptr = seed_text; unsigned long seed; - seed = strtoul(seed_text, &endptr, 10); + seed = strtoul(seed_text, (char **)&endptr, 10); if (*endptr != '\0' || seed > 4294967295UL || (errno == ERANGE && seed == ULONG_MAX)) @@ -604,7 +604,7 @@ init_hash_secret(int use_hash_seed, _PyInitError _Py_HashRandomization_Init(_PyCoreConfig *core_config) { - char *seed_text; + const char *seed_text; int use_hash_seed = core_config->use_hash_seed; unsigned long hash_seed = core_config->hash_seed; diff --git a/Python/dynamic_annotations.c b/Python/dynamic_annotations.c index 10511da4661..7febaa09df1 100644 --- a/Python/dynamic_annotations.c +++ b/Python/dynamic_annotations.c @@ -120,7 +120,7 @@ static int GetRunningOnValgrind(void) { #endif #ifndef _MSC_VER - char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND"); + const char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND"); if (running_on_valgrind_str) { return strcmp(running_on_valgrind_str, "0") != 0; } diff --git a/Python/frozenmain.c b/Python/frozenmain.c index 77602d70fa8..a3b619671bd 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -23,7 +23,7 @@ Py_FrozenMain(int argc, char **argv) exit(1); } - char *p; + const char *p; int i, n, sts = 1; int inspect = 0; int unbuffered = 0; diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 6a03f7dca1b..53ddfc997da 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -168,7 +168,7 @@ Py_SetPath(const wchar_t *path) void -Py_SetPythonHome(wchar_t *home) +Py_SetPythonHome(const wchar_t *home) { if (home == NULL) { return; @@ -189,7 +189,7 @@ Py_SetPythonHome(wchar_t *home) void -Py_SetProgramName(wchar_t *program_name) +Py_SetProgramName(const wchar_t *program_name) { if (program_name == NULL || program_name[0] == L'\0') { return; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 0b3aa98ba2e..fdb09d910da 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -414,7 +414,7 @@ static _LocaleCoercionTarget _TARGET_LOCALES[] = { {NULL} }; -static char * +static const char * get_default_standard_stream_error_handler(void) { const char *ctype_loc = setlocale(LC_CTYPE, NULL); @@ -440,7 +440,7 @@ get_default_standard_stream_error_handler(void) } #ifdef PY_COERCE_C_LOCALE -static const char *_C_LOCALE_COERCION_WARNING = +static const char _C_LOCALE_COERCION_WARNING[] = "Python detected LC_CTYPE=C: LC_CTYPE coerced to %.20s (set another locale " "or PYTHONCOERCECLOCALE=0 to disable this locale coercion behavior).\n"; @@ -1757,7 +1757,8 @@ init_sys_streams(void) PyObject *std = NULL; int fd; PyObject * encoding_attr; - char *pythonioencoding = NULL, *encoding, *errors; + char *pythonioencoding = NULL; + const char *encoding, *errors; _PyInitError res = _Py_INIT_OK(); /* Hack to avoid a nasty recursion issue when Python is invoked diff --git a/Python/sysmodule.c b/Python/sysmodule.c index eeeaa7240e7..f10099b5232 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -100,7 +100,7 @@ static PyObject * sys_breakpointhook(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *keywords) { assert(!PyErr_Occurred()); - char *envar = Py_GETENV("PYTHONBREAKPOINT"); + const char *envar = Py_GETENV("PYTHONBREAKPOINT"); if (envar == NULL || strlen(envar) == 0) { envar = "pdb.set_trace"; @@ -109,8 +109,8 @@ sys_breakpointhook(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject * /* The breakpoint is explicitly no-op'd. */ Py_RETURN_NONE; } - char *last_dot = strrchr(envar, '.'); - char *attrname = NULL; + const char *last_dot = strrchr(envar, '.'); + const char *attrname = NULL; PyObject *modulepath = NULL; if (last_dot == NULL) { diff --git a/Python/thread.c b/Python/thread.c index 7eac836dc16..07743840693 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -61,7 +61,7 @@ void PyThread_init_thread(void) { #ifdef Py_DEBUG - char *p = Py_GETENV("PYTHONTHREADDEBUG"); + const char *p = Py_GETENV("PYTHONTHREADDEBUG"); if (p) { if (*p) From webhook-mailer at python.org Tue Dec 12 12:03:11 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 17:03:11 -0000 Subject: [Python-checkins] Fix implementation dependent assertion in test_plistlib. (#4813) Message-ID: https://github.com/python/cpython/commit/0e069a1597ce6791a5f0da8329da2c446766c80e commit: 0e069a1597ce6791a5f0da8329da2c446766c80e branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-12T19:03:08+02:00 summary: Fix implementation dependent assertion in test_plistlib. (#4813) It is failed with an advanced optimizer. files: M Lib/test/test_plistlib.py diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py index ae8b6239690..8d8e0a750a2 100644 --- a/Lib/test/test_plistlib.py +++ b/Lib/test/test_plistlib.py @@ -320,7 +320,8 @@ def test_tuple_members(self): 'second': [1, 2], 'third': [3, 4], }) - self.assertIsNot(pl2['first'], pl2['second']) + if fmt != plistlib.FMT_BINARY: + self.assertIsNot(pl2['first'], pl2['second']) def test_list_members(self): pl = { From webhook-mailer at python.org Tue Dec 12 12:21:54 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 17:21:54 -0000 Subject: [Python-checkins] Fix improper use of re.escape() in tests. (#4814) Message-ID: https://github.com/python/cpython/commit/b748e3b2586e44bfc7011b601bce9cc6d16d89f1 commit: b748e3b2586e44bfc7011b601bce9cc6d16d89f1 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-12T19:21:50+02:00 summary: Fix improper use of re.escape() in tests. (#4814) files: M Lib/test/test_re.py diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 2344d71abf2..aaed3d893aa 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -109,7 +109,7 @@ def test_basic_re_sub(self): s = r"\1\1" self.assertEqual(re.sub('(.)', s, 'x'), 'xx') - self.assertEqual(re.sub('(.)', re.escape(s), 'x'), s) + self.assertEqual(re.sub('(.)', s.replace('\\', r'\\'), 'x'), s) self.assertEqual(re.sub('(.)', lambda m: s, 'x'), s) self.assertEqual(re.sub('(?Px)', r'\g\g', 'xx'), 'xxxx') From webhook-mailer at python.org Tue Dec 12 12:53:09 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 17:53:09 -0000 Subject: [Python-checkins] Fix implementation dependent assertion in test_plistlib. (GH-4813) (#4815) Message-ID: https://github.com/python/cpython/commit/eb2f222aaeab20a65defe69f7b57c505b8ef87b1 commit: eb2f222aaeab20a65defe69f7b57c505b8ef87b1 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-12T19:53:02+02:00 summary: Fix implementation dependent assertion in test_plistlib. (GH-4813) (#4815) It is failed with an advanced optimizer. (cherry picked from commit 0e069a1597ce6791a5f0da8329da2c446766c80e) files: M Lib/test/test_plistlib.py diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py index 90641a7635c..d47c607329c 100644 --- a/Lib/test/test_plistlib.py +++ b/Lib/test/test_plistlib.py @@ -321,7 +321,8 @@ def test_tuple_members(self): 'second': [1, 2], 'third': [3, 4], }) - self.assertIsNot(pl2['first'], pl2['second']) + if fmt != plistlib.FMT_BINARY: + self.assertIsNot(pl2['first'], pl2['second']) def test_list_members(self): pl = { From webhook-mailer at python.org Tue Dec 12 13:29:07 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 18:29:07 -0000 Subject: [Python-checkins] Fix improper use of re.escape() in tests. (GH-4814) (#4816) Message-ID: https://github.com/python/cpython/commit/f4b814f9a23287716493a612e041f7cd4ea297ac commit: f4b814f9a23287716493a612e041f7cd4ea297ac branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-12T20:29:05+02:00 summary: Fix improper use of re.escape() in tests. (GH-4814) (#4816) (cherry picked from commit b748e3b2586e44bfc7011b601bce9cc6d16d89f1) files: M Lib/test/test_re.py diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index e23e5a9a6ca..2b74373ffae 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -112,7 +112,7 @@ def test_basic_re_sub(self): s = r"\1\1" self.assertEqual(re.sub('(.)', s, 'x'), 'xx') - self.assertEqual(re.sub('(.)', re.escape(s), 'x'), s) + self.assertEqual(re.sub('(.)', s.replace('\\', r'\\'), 'x'), s) self.assertEqual(re.sub('(.)', lambda m: s, 'x'), s) self.assertEqual(re.sub('(?Px)', r'\g\g', 'xx'), 'xxxx') From webhook-mailer at python.org Tue Dec 12 13:49:28 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 12 Dec 2017 18:49:28 -0000 Subject: [Python-checkins] Fix improper use of re.escape() in tests. (GH-4814) (#4817) Message-ID: https://github.com/python/cpython/commit/d663549a6a2c50450ba51f393ed6855181a36a9e commit: d663549a6a2c50450ba51f393ed6855181a36a9e branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-12T20:49:18+02:00 summary: Fix improper use of re.escape() in tests. (GH-4814) (#4817) (cherry picked from commit b748e3b2586e44bfc7011b601bce9cc6d16d89f1) files: M Lib/test/test_re.py diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 174c5ca462c..ae314841c68 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -58,7 +58,7 @@ def test_basic_re_sub(self): s = r"\1\1" self.assertEqual(re.sub('(.)', s, 'x'), 'xx') - self.assertEqual(re.sub('(.)', re.escape(s), 'x'), s) + self.assertEqual(re.sub('(.)', s.replace('\\', r'\\'), 'x'), s) self.assertEqual(re.sub('(.)', lambda m: s, 'x'), s) self.assertEqual(re.sub('(?Px)', '\g\g', 'xx'), 'xxxx') From webhook-mailer at python.org Tue Dec 12 16:59:51 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 12 Dec 2017 21:59:51 -0000 Subject: [Python-checkins] bpo-32230: Set sys.warnoptions with -X dev (#4820) Message-ID: https://github.com/python/cpython/commit/747f48e2e92390c44c72f52a1239959601cde157 commit: 747f48e2e92390c44c72f52a1239959601cde157 branch: master author: Victor Stinner committer: GitHub date: 2017-12-12T22:59:48+01:00 summary: bpo-32230: Set sys.warnoptions with -X dev (#4820) Rather than supporting dev mode directly in the warnings module, this instead adjusts the initialisation code to add an extra 'default' entry to sys.warnoptions when dev mode is enabled. This ensures that dev mode behaves *exactly* as if `-Wdefault` had been passed on the command line, including in the way it interacts with `sys.warnoptions`, and with other command line flags like `-bb`. Fix also bpo-20361: have -b & -bb options take precedence over any other warnings options. Patch written by Nick Coghlan, with minor modifications of Victor Stinner. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-06-20-18-34.bpo-32230.PgGQaB.rst A Misc/NEWS.d/next/Core and Builtins/2017-12-07-17-22-30.bpo-20361.zQUmbi.rst M Doc/tools/susp-ignored.csv M Doc/using/cmdline.rst M Doc/whatsnew/3.7.rst M Lib/subprocess.py M Lib/test/test_cmd_line.py M Lib/test/test_warnings/__init__.py M Lib/unittest/test/test_runner.py M Lib/warnings.py M Modules/main.c M Python/_warnings.c diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index d52f81b76b5..48dd53f85d2 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -327,3 +327,6 @@ whatsnew/changelog,,:end,str[start:end] library/binascii,,`,'`' library/uu,,`,'`' whatsnew/3.7,,`,'`' +whatsnew/3.7,,::,error::BytesWarning +whatsnew/changelog,,::,error::BytesWarning +whatsnew/changelog,,::,default::BytesWarning diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 716bc821b4a..e32f77e7ffc 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -430,11 +430,7 @@ Miscellaneous options not be more verbose than the default if the code is correct: new warnings are only emitted when an issue is detected. Effect of the developer mode: - * Warning filters: add a filter to display all warnings (``"default"`` - action), except of :exc:`BytesWarning` which still depends on the - :option:`-b` option, and use ``"always"`` action for - :exc:`ResourceWarning` warnings. For example, display - :exc:`DeprecationWarning` warnings. + * Add ``default`` warning filter, as :option:`-W` ``default``. * Install debug hooks on memory allocators: see the :c:func:`PyMem_SetupDebugHooks` C function. * Enable the :mod:`faulthandler` module to dump the Python traceback diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 34876626597..58bfaef282c 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -188,14 +188,11 @@ resolution on Linux and Windows. New Development Mode: -X dev ---------------------------- -Add a new "development mode": ``-X dev`` command line option to enable debug -checks at runtime. - -In short, ``python3 -X dev ...`` behaves as ``PYTHONMALLOC=debug python3 -W -default -X faulthandler ...``, except that the PYTHONMALLOC environment -variable is not set in practice. - -See :option:`-X` ``dev`` for the details. +Add a new "development mode": :option:`-X` ``dev`` command line option and +:envvar:`PYTHONDEVMODE` environment variable to enable CPython's "development +mode", introducing additional runtime checks which are too expensive to be +enabled by default. See :option:`-X` ``dev`` documentation for the effects of +the development mode. Hash-based pycs --------------- @@ -481,6 +478,29 @@ Function :func:`~uu.encode` now accepts an optional *backtick* keyword argument. When it's true, zeros are represented by ``'`'`` instead of spaces. (Contributed by Xiang Zhang in :issue:`30103`.) +warnings +-------- + +The initialization of the default warnings filters has changed as follows: + +* warnings enabled via command line options (including those for :option:`-b` + and the new CPython-specific ``-X dev`` option) are always passed to the + warnings machinery via the ``sys.warnoptions`` attribute. +* warnings filters enabled via the command line or the environment now have the + following precedence order: + + * the ``BytesWarning`` filter for :option:`-b` (or ``-bb``) + * any filters specified with :option:`-W` + * any filters specified with :envvar:`PYTHONWARNINGS` + * any other CPython specific filters (e.g. the ``default`` filter added + for the new ``-X dev`` mode) + * any implicit filters defined directly by the warnings machinery +* in CPython debug builds, all warnings are now displayed by default (the + implicit filter list is empty) + +(Contributed by Nick Coghlan and Victor Stinner in :issue:`20361`, +:issue:`32043`, and :issue:`32230`) + xml.etree --------- @@ -854,6 +874,12 @@ Other CPython implementation changes either in embedding applications, or in CPython itself. (Contributed by Nick Coghlan and Eric Snow as part of :issue:`22257`.) +* Due to changes in the way the default warnings filters are configured, + setting ``Py_BytesWarningFlag`` to a value greater than one is no longer + sufficient to both emit ``BytesWarning`` messages and have them converted + to exceptions. Instead, the flag must be set (to cause the warnings to be + emitted in the first place), and an explicit ``error::BytesWarning`` + warnings filter added to convert them to exceptions. Documentation ============= diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 35bfddde4e9..301433cdf5d 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -241,7 +241,7 @@ def _optim_args_from_interpreter_flags(): def _args_from_interpreter_flags(): """Return a list of command-line arguments reproducing the current - settings in sys.flags and sys.warnoptions.""" + settings in sys.flags, sys.warnoptions and sys._xoptions.""" flag_opt_map = { 'debug': 'd', # 'inspect': 'i', @@ -262,12 +262,22 @@ def _args_from_interpreter_flags(): args.append('-' + opt * v) # -W options - for opt in sys.warnoptions: + warnopts = sys.warnoptions[:] + bytes_warning = sys.flags.bytes_warning + xoptions = getattr(sys, '_xoptions', {}) + dev_mode = ('dev' in xoptions) + + if bytes_warning > 1: + warnopts.remove("error::BytesWarning") + elif bytes_warning: + warnopts.remove("default::BytesWarning") + if dev_mode: + warnopts.remove('default') + for opt in warnopts: args.append('-W' + opt) # -X options - xoptions = getattr(sys, '_xoptions', {}) - if 'dev' in xoptions: + if dev_mode: args.extend(('-X', 'dev')) for opt in ('faulthandler', 'tracemalloc', 'importtime', 'showalloccount', 'showrefcount'): diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 383302bad8b..2aff51bdc13 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -14,6 +14,11 @@ interpreter_requires_environment ) + +# Debug build? +Py_DEBUG = hasattr(sys, "gettotalrefcount") + + # XXX (ncoghlan): Move to script_helper and make consistent with run_python def _kill_python_and_exit_code(p): data = kill_python(p) @@ -97,7 +102,7 @@ def run_python(*args): # "-X showrefcount" shows the refcount, but only in debug builds rc, out, err = run_python('-X', 'showrefcount', '-c', code) self.assertEqual(out.rstrip(), b"{'showrefcount': True}") - if hasattr(sys, 'gettotalrefcount'): # debug build + if Py_DEBUG: self.assertRegex(err, br'^\[\d+ refs, \d+ blocks\]') else: self.assertEqual(err, b'') @@ -541,31 +546,26 @@ def test_xdev(self): code = ("import sys, warnings; " "print(' '.join('%s::%s' % (f[0], f[2].__name__) " "for f in warnings.filters))") + if Py_DEBUG: + expected_filters = "default::Warning" + else: + expected_filters = ("default::Warning " + "ignore::DeprecationWarning " + "ignore::PendingDeprecationWarning " + "ignore::ImportWarning " + "ignore::ResourceWarning") out = self.run_xdev("-c", code) - self.assertEqual(out, - "ignore::BytesWarning " - "default::ResourceWarning " - "default::Warning") + self.assertEqual(out, expected_filters) out = self.run_xdev("-b", "-c", code) - self.assertEqual(out, - "default::BytesWarning " - "default::ResourceWarning " - "default::Warning") + self.assertEqual(out, f"default::BytesWarning {expected_filters}") out = self.run_xdev("-bb", "-c", code) - self.assertEqual(out, - "error::BytesWarning " - "default::ResourceWarning " - "default::Warning") + self.assertEqual(out, f"error::BytesWarning {expected_filters}") out = self.run_xdev("-Werror", "-c", code) - self.assertEqual(out, - "error::Warning " - "ignore::BytesWarning " - "default::ResourceWarning " - "default::Warning") + self.assertEqual(out, f"error::Warning {expected_filters}") # Memory allocator debug hooks try: @@ -592,6 +592,46 @@ def test_xdev(self): out = self.run_xdev("-c", code) self.assertEqual(out, "True") + def check_warnings_filters(self, cmdline_option, envvar, use_pywarning=False): + if use_pywarning: + code = ("import sys; from test.support import import_fresh_module; " + "warnings = import_fresh_module('warnings', blocked=['_warnings']); ") + else: + code = "import sys, warnings; " + code += ("print(' '.join('%s::%s' % (f[0], f[2].__name__) " + "for f in warnings.filters))") + args = (sys.executable, '-W', cmdline_option, '-bb', '-c', code) + env = dict(os.environ) + env.pop('PYTHONDEVMODE', None) + env["PYTHONWARNINGS"] = envvar + proc = subprocess.run(args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + env=env) + self.assertEqual(proc.returncode, 0, proc) + return proc.stdout.rstrip() + + def test_warnings_filter_precedence(self): + expected_filters = ("error::BytesWarning " + "once::UserWarning " + "always::UserWarning") + if not Py_DEBUG: + expected_filters += (" " + "ignore::DeprecationWarning " + "ignore::PendingDeprecationWarning " + "ignore::ImportWarning " + "ignore::ResourceWarning") + + out = self.check_warnings_filters("once::UserWarning", + "always::UserWarning") + self.assertEqual(out, expected_filters) + + out = self.check_warnings_filters("once::UserWarning", + "always::UserWarning", + use_pywarning=True) + self.assertEqual(out, expected_filters) + def check_pythonmalloc(self, env_var, name): code = 'import _testcapi; print(_testcapi.pymem_getallocatorsname())' env = dict(os.environ) @@ -611,13 +651,12 @@ def check_pythonmalloc(self, env_var, name): def test_pythonmalloc(self): # Test the PYTHONMALLOC environment variable - pydebug = hasattr(sys, "gettotalrefcount") pymalloc = support.with_pymalloc() if pymalloc: - default_name = 'pymalloc_debug' if pydebug else 'pymalloc' + default_name = 'pymalloc_debug' if Py_DEBUG else 'pymalloc' default_name_debug = 'pymalloc_debug' else: - default_name = 'malloc_debug' if pydebug else 'malloc' + default_name = 'malloc_debug' if Py_DEBUG else 'malloc' default_name_debug = 'malloc_debug' tests = [ diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index e60bc4d27f6..039c96e02c9 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -1110,20 +1110,23 @@ class EnvironmentVariableTests(BaseTest): def test_single_warning(self): rc, stdout, stderr = assert_python_ok("-c", "import sys; sys.stdout.write(str(sys.warnoptions))", - PYTHONWARNINGS="ignore::DeprecationWarning") + PYTHONWARNINGS="ignore::DeprecationWarning", + PYTHONDEVMODE="") self.assertEqual(stdout, b"['ignore::DeprecationWarning']") def test_comma_separated_warnings(self): rc, stdout, stderr = assert_python_ok("-c", "import sys; sys.stdout.write(str(sys.warnoptions))", - PYTHONWARNINGS="ignore::DeprecationWarning,ignore::UnicodeWarning") + PYTHONWARNINGS="ignore::DeprecationWarning,ignore::UnicodeWarning", + PYTHONDEVMODE="") self.assertEqual(stdout, b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']") def test_envvar_and_command_line(self): rc, stdout, stderr = assert_python_ok("-Wignore::UnicodeWarning", "-c", "import sys; sys.stdout.write(str(sys.warnoptions))", - PYTHONWARNINGS="ignore::DeprecationWarning") + PYTHONWARNINGS="ignore::DeprecationWarning", + PYTHONDEVMODE="") self.assertEqual(stdout, b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']") @@ -1131,7 +1134,8 @@ def test_conflicting_envvar_and_command_line(self): rc, stdout, stderr = assert_python_failure("-Werror::DeprecationWarning", "-c", "import sys, warnings; sys.stdout.write(str(sys.warnoptions)); " "warnings.warn('Message', DeprecationWarning)", - PYTHONWARNINGS="default::DeprecationWarning") + PYTHONWARNINGS="default::DeprecationWarning", + PYTHONDEVMODE="") self.assertEqual(stdout, b"['default::DeprecationWarning', 'error::DeprecationWarning']") self.assertEqual(stderr.splitlines(), @@ -1145,7 +1149,8 @@ def test_nonascii(self): rc, stdout, stderr = assert_python_ok("-c", "import sys; sys.stdout.write(str(sys.warnoptions))", PYTHONIOENCODING="utf-8", - PYTHONWARNINGS="ignore:Deprecaci?nWarning") + PYTHONWARNINGS="ignore:Deprecaci?nWarning", + PYTHONDEVMODE="") self.assertEqual(stdout, "['ignore:Deprecaci?nWarning']".encode('utf-8')) diff --git a/Lib/unittest/test/test_runner.py b/Lib/unittest/test/test_runner.py index ddc498c230c..3c4005671f7 100644 --- a/Lib/unittest/test/test_runner.py +++ b/Lib/unittest/test/test_runner.py @@ -289,7 +289,7 @@ def get_parse_out_err(p): at_msg = b'Please use assertTrue instead.' # no args -> all the warnings are printed, unittest warnings only once - p = subprocess.Popen([sys.executable, '_test_warnings.py'], **opts) + p = subprocess.Popen([sys.executable, '-E', '_test_warnings.py'], **opts) with p: out, err = get_parse_out_err(p) self.assertIn(b'OK', err) diff --git a/Lib/warnings.py b/Lib/warnings.py index 4e7241fe6ca..f4331c8ac38 100644 --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -519,34 +519,11 @@ def _filters_mutated(): # Module initialization _processoptions(sys.warnoptions) if not _warnings_defaults: - dev_mode = ('dev' in getattr(sys, '_xoptions', {})) - py_debug = hasattr(sys, 'gettotalrefcount') - - if not(dev_mode or py_debug): - silence = [ImportWarning, PendingDeprecationWarning] - silence.append(DeprecationWarning) - for cls in silence: - simplefilter("ignore", category=cls) - - bytes_warning = sys.flags.bytes_warning - if bytes_warning > 1: - bytes_action = "error" - elif bytes_warning: - bytes_action = "default" - else: - bytes_action = "ignore" - simplefilter(bytes_action, category=BytesWarning, append=1) - - # resource usage warnings are enabled by default in pydebug mode - if dev_mode or py_debug: - resource_action = "default" - else: - resource_action = "ignore" - simplefilter(resource_action, category=ResourceWarning, append=1) - - if dev_mode: - simplefilter("default", category=Warning, append=1) - - del py_debug, dev_mode + # Several warning categories are ignored by default in Py_DEBUG builds + if not hasattr(sys, 'gettotalrefcount'): + simplefilter("ignore", category=DeprecationWarning, append=1) + simplefilter("ignore", category=PendingDeprecationWarning, append=1) + simplefilter("ignore", category=ImportWarning, append=1) + simplefilter("ignore", category=ResourceWarning, append=1) del _warnings_defaults diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-06-20-18-34.bpo-32230.PgGQaB.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-06-20-18-34.bpo-32230.PgGQaB.rst new file mode 100644 index 00000000000..b8656e4f25a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-06-20-18-34.bpo-32230.PgGQaB.rst @@ -0,0 +1,3 @@ +`-X dev` now injects a ``'default'`` entry into sys.warnoptions, ensuring +that it behaves identically to actually passing ``-Wdefault`` at the command +line. diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-07-17-22-30.bpo-20361.zQUmbi.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-07-17-22-30.bpo-20361.zQUmbi.rst new file mode 100644 index 00000000000..df7aed7f07a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-07-17-22-30.bpo-20361.zQUmbi.rst @@ -0,0 +1,4 @@ +``-b`` and ``-bb`` now inject ``'default::BytesWarning'`` and +``error::BytesWarning`` entries into ``sys.warnoptions``, ensuring that they +take precedence over any other warning filters configured via the ``-W`` +option or the ``PYTHONWARNINGS`` environment variable. diff --git a/Modules/main.c b/Modules/main.c index 68ee616da62..ac8a38c8f84 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -774,11 +774,73 @@ pymain_add_warnings_optlist(_Py_OptList *warnings) return 0; } + +static int +pymain_add_warning_dev_mode(_PyCoreConfig *core_config) +{ + if (core_config->dev_mode) { + PyObject *option = PyUnicode_FromString("default"); + if (option == NULL) { + return -1; + } + if (_PySys_AddWarnOptionWithError(option)) { + Py_DECREF(option); + return -1; + } + Py_DECREF(option); + } + return 0; +} + + +static int +pymain_add_warning_bytes_flag(int bytes_warning_flag) +{ + /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c + * don't even try to emit a warning, so we skip setting the filter in that + * case. + */ + if (bytes_warning_flag) { + const char *filter = (bytes_warning_flag > 1) ? "error::BytesWarning": + "default::BytesWarning"; + PyObject *option = PyUnicode_FromString(filter); + if (option == NULL) { + return -1; + } + if (_PySys_AddWarnOptionWithError(option)) { + Py_DECREF(option); + return -1; + } + Py_DECREF(option); + } + return 0; +} + + static int pymain_add_warnings_options(_PyMain *pymain) { PySys_ResetWarnOptions(); + /* The priority order for warnings configuration is (highest precedence + * first): + * + * - the BytesWarning filter, if needed ('-b', '-bb') + * - any '-W' command line options; then + * - the 'PYTHONWARNINGS' environment variable; then + * - the dev mode filter ('-X dev', 'PYTHONDEVMODE'); then + * - any implicit filters added by _warnings.c/warnings.py + * + * All settings except the last are passed to the warnings module via + * the `sys.warnoptions` list. Since the warnings module works on the basis + * of "the most recently added filter will be checked first", we add + * the lowest precedence entries first so that later entries override them. + */ + + if (pymain_add_warning_dev_mode(&pymain->core_config) < 0) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } if (pymain_add_warnings_optlist(&pymain->env_warning_options) < 0) { pymain->err = _Py_INIT_NO_MEMORY(); return -1; @@ -787,6 +849,10 @@ pymain_add_warnings_options(_PyMain *pymain) pymain->err = _Py_INIT_NO_MEMORY(); return -1; } + if (pymain_add_warning_bytes_flag(pymain->cmdline.bytes_warning) < 0) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } return 0; } diff --git a/Python/_warnings.c b/Python/_warnings.c index 29370369e25..7b2bdd5462c 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -11,9 +11,9 @@ MODULE_NAME " provides basic warning filtering support.\n" _Py_IDENTIFIER(argv); _Py_IDENTIFIER(stderr); +#ifndef Py_DEBUG _Py_IDENTIFIER(ignore); -_Py_IDENTIFIER(error); -_Py_static_string(PyId_default, "default"); +#endif static int check_matched(PyObject *obj, PyObject *arg) @@ -1156,6 +1156,7 @@ static PyMethodDef warnings_functions[] = { }; +#ifndef Py_DEBUG static PyObject * create_filter(PyObject *category, _Py_Identifier *id) { @@ -1168,70 +1169,40 @@ create_filter(PyObject *category, _Py_Identifier *id) return PyTuple_Pack(5, action_str, Py_None, category, Py_None, _PyLong_Zero); } +#endif + static PyObject * init_filters(const _PyCoreConfig *config) { - int dev_mode = config->dev_mode; - - Py_ssize_t count = 2; - if (dev_mode) { - count++; - } -#ifndef Py_DEBUG - if (!dev_mode) { - count += 3; - } -#endif - PyObject *filters = PyList_New(count); - if (filters == NULL) - return NULL; - - size_t pos = 0; /* Post-incremented in each use. */ -#ifndef Py_DEBUG - if (!dev_mode) { - PyList_SET_ITEM(filters, pos++, - create_filter(PyExc_DeprecationWarning, &PyId_ignore)); - PyList_SET_ITEM(filters, pos++, - create_filter(PyExc_PendingDeprecationWarning, &PyId_ignore)); - PyList_SET_ITEM(filters, pos++, - create_filter(PyExc_ImportWarning, &PyId_ignore)); - } -#endif - - _Py_Identifier *bytes_action; - if (Py_BytesWarningFlag > 1) - bytes_action = &PyId_error; - else if (Py_BytesWarningFlag) - bytes_action = &PyId_default; - else - bytes_action = &PyId_ignore; - PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning, - bytes_action)); - - _Py_Identifier *resource_action; - /* resource usage warnings are enabled by default in pydebug mode */ #ifdef Py_DEBUG - resource_action = &PyId_default; + /* Py_DEBUG builds show all warnings by default */ + return PyList_New(0); #else - resource_action = (dev_mode ? &PyId_default: &PyId_ignore); -#endif - PyList_SET_ITEM(filters, pos++, create_filter(PyExc_ResourceWarning, - resource_action)); - - if (dev_mode) { - PyList_SET_ITEM(filters, pos++, - create_filter(PyExc_Warning, &PyId_default)); + /* Other builds ignore a number of warning categories by default */ + PyObject *filters = PyList_New(4); + if (filters == NULL) { + return NULL; } + size_t pos = 0; /* Post-incremented in each use. */ + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_DeprecationWarning, &PyId_ignore)); + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_PendingDeprecationWarning, &PyId_ignore)); + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_ImportWarning, &PyId_ignore)); + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_ResourceWarning, &PyId_ignore)); + for (size_t x = 0; x < pos; x++) { if (PyList_GET_ITEM(filters, x) == NULL) { Py_DECREF(filters); return NULL; } } - return filters; +#endif } static struct PyModuleDef warningsmodule = { From webhook-mailer at python.org Tue Dec 12 17:15:02 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 12 Dec 2017 22:15:02 -0000 Subject: [Python-checkins] bpo-32101: Fix tests for PYTHONDEVMODE=1 (#4821) Message-ID: https://github.com/python/cpython/commit/721e25c6535d08bd3d4d891fb2b540472e19f899 commit: 721e25c6535d08bd3d4d891fb2b540472e19f899 branch: master author: Victor Stinner committer: GitHub date: 2017-12-12T23:15:00+01:00 summary: bpo-32101: Fix tests for PYTHONDEVMODE=1 (#4821) test_asycio: remove also aio_path which was used when asyncio was developed outside the stdlib. files: M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_faulthandler.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 8b08ed16634..e43fe6948af 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -802,17 +802,20 @@ def test_env_var_debug(self): self.assertEqual(stdout.rstrip(), b'False') sts, stdout, stderr = assert_python_ok('-c', code, - PYTHONASYNCIODEBUG='') + PYTHONASYNCIODEBUG='', + PYTHONDEVMODE='') self.assertEqual(stdout.rstrip(), b'False') sts, stdout, stderr = assert_python_ok('-c', code, - PYTHONASYNCIODEBUG='1') + PYTHONASYNCIODEBUG='1', + PYTHONDEVMODE='') self.assertEqual(stdout.rstrip(), b'True') sts, stdout, stderr = assert_python_ok('-E', '-c', code, PYTHONASYNCIODEBUG='1') self.assertEqual(stdout.rstrip(), b'False') + # -X dev sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev', '-c', code) self.assertEqual(stdout.rstrip(), b'True') diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 071481dbc26..0838ebf3a7b 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2257,33 +2257,31 @@ def test_return_exceptions(self): self.assertEqual(fut.result(), [3, 1, exc, exc2]) def test_env_var_debug(self): - aio_path = os.path.dirname(os.path.dirname(asyncio.__file__)) - code = '\n'.join(( 'import asyncio.coroutines', 'print(asyncio.coroutines._DEBUG)')) # Test with -E to not fail if the unit test was run with # PYTHONASYNCIODEBUG set to a non-empty string - sts, stdout, stderr = assert_python_ok('-E', '-c', code, - PYTHONPATH=aio_path) + sts, stdout, stderr = assert_python_ok('-E', '-c', code) self.assertEqual(stdout.rstrip(), b'False') sts, stdout, stderr = assert_python_ok('-c', code, PYTHONASYNCIODEBUG='', - PYTHONPATH=aio_path) + PYTHONDEVMODE='') self.assertEqual(stdout.rstrip(), b'False') sts, stdout, stderr = assert_python_ok('-c', code, PYTHONASYNCIODEBUG='1', - PYTHONPATH=aio_path) + PYTHONDEVMODE='') self.assertEqual(stdout.rstrip(), b'True') sts, stdout, stderr = assert_python_ok('-E', '-c', code, PYTHONASYNCIODEBUG='1', - PYTHONPATH=aio_path) + PYTHONDEVMODE='') self.assertEqual(stdout.rstrip(), b'False') + # -X dev sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev', '-c', code) self.assertEqual(stdout.rstrip(), b'True') diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 3647bfc719e..d6dc4ba55d9 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -332,13 +332,9 @@ def test_is_enabled(self): def test_disabled_by_default(self): # By default, the module should be disabled code = "import faulthandler; print(faulthandler.is_enabled())" - args = filter(None, (sys.executable, - "-E" if sys.flags.ignore_environment else "", - "-c", code)) - env = os.environ.copy() - env.pop("PYTHONFAULTHANDLER", None) + args = (sys.executable, "-E", "-c", code) # don't use assert_python_ok() because it always enables faulthandler - output = subprocess.check_output(args, env=env) + output = subprocess.check_output(args) self.assertEqual(output.rstrip(), b"False") def test_sys_xoptions(self): @@ -357,15 +353,17 @@ def test_env_var(self): # empty env var code = "import faulthandler; print(faulthandler.is_enabled())" args = (sys.executable, "-c", code) - env = os.environ.copy() + env = dict(os.environ) env['PYTHONFAULTHANDLER'] = '' + env['PYTHONDEVMODE'] = '' # don't use assert_python_ok() because it always enables faulthandler output = subprocess.check_output(args, env=env) self.assertEqual(output.rstrip(), b"False") # non-empty env var - env = os.environ.copy() + env = dict(os.environ) env['PYTHONFAULTHANDLER'] = '1' + env['PYTHONDEVMODE'] = '' output = subprocess.check_output(args, env=env) self.assertEqual(output.rstrip(), b"True") From webhook-mailer at python.org Tue Dec 12 17:29:30 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 12 Dec 2017 22:29:30 -0000 Subject: [Python-checkins] import.c: Fix a GCC warning (#4822) Message-ID: https://github.com/python/cpython/commit/d233796f7d444c67fe51b7dd9521d548e650286f commit: d233796f7d444c67fe51b7dd9521d548e650286f branch: master author: Victor Stinner committer: GitHub date: 2017-12-12T23:29:28+01:00 summary: import.c: Fix a GCC warning (#4822) Fix the warning: Python/import.c: warning: comparison between signed and unsigned integer expressions if ((i + n + 1) <= PY_SSIZE_T_MAX / sizeof(struct _inittab)) { files: M Python/import.c diff --git a/Python/import.c b/Python/import.c index 892f3d1c6e4..d5dad1a6a30 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2308,7 +2308,7 @@ PyImport_ExtendInittab(struct _inittab *newtab) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); /* Allocate new memory for the combined table */ - if ((i + n + 1) <= PY_SSIZE_T_MAX / sizeof(struct _inittab)) { + if ((i + n + 1) <= PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(struct _inittab)) { size_t size = sizeof(struct _inittab) * (i + n + 1); p = PyMem_RawRealloc(inittab_copy, size); } From lp_benchmark_robot at intel.com Tue Dec 12 18:24:46 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Tue, 12 Dec 2017 15:24:46 -0800 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2017-12-12 Message-ID: Results for project python/master, build date: 2017-12-12 03:03:21-08:00. - commit: 5ce0a2a - previous commit: 19d0d54 - revision date: 2017-12-12 11:22:30+01:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.970% | -0.343% | +4.135% | +9.021% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.109% | -0.327% | +22.977% | +12.003% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.042% | -0.455% | +23.176% | +12.959% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.328% | +0.360% | +21.713% | +8.489% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.814% | -0.364% | +7.303% | +13.529% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.805% | -0.231% | +9.267% | +13.146% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.168% | -0.067% | +7.284% | +11.289% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.404% | +0.072% | -0.336% | +9.798% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.811% | -0.492% | +7.602% | +19.961% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 5.664% | -2.331% | +10.867% | +16.480% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 3.863% | -0.717% | +1.997% | +8.317% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.788% | -0.053% | +3.539% | +5.820% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.605% | +0.196% | +1.860% | +7.743% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.883% | -0.598% | +12.441% | +11.351% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.732% | -1.338% | +8.179% | +12.287% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.685% | -0.398% | +4.589% | +13.859% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.822% | -0.093% | +9.513% | +13.441% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.138% | +0.232% | +7.275% | +9.924% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.863% | +0.022% | +2.677% | +10.948% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 0.973% | +0.029% | +0.881% | +10.825% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.614% | -1.405% | +5.430% | +14.663% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.815% | +0.583% | +46.431% | +13.202% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.910% | -2.202% | +5.895% | +15.877% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.999% | -0.067% | +16.163% | +13.855% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.536% | -0.142% | +5.731% | +12.156% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 2.119% | -0.068% | +3.535% | +6.116% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.525% | -0.033% | -1.364% | +1.010% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.573% | +0.196% | +5.475% | +7.773% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.723% | -0.298% | +7.356% | +8.464% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.359% | +0.590% | +1.279% | +21.938% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.251% | +0.024% | +1.584% | +23.106% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.668% | +0.137% | +2.381% | +21.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.573% | -0.232% | +9.137% | +12.032% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.071% | -0.032% | +0.011% | +10.267% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.144% | +0.060% | +10.235% | +5.123% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.117% | +0.154% | +1.457% | +5.009% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.362% | -0.118% | +9.791% | +14.319% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.186% | -0.419% | +4.241% | +8.616% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.293% | +0.167% | -0.768% | +10.233% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 3.003% | -0.689% | -3.996% | +5.110% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 0.895% | -0.162% | +4.101% | +9.791% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.231% | -0.229% | +7.654% | +16.019% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.618% | -0.238% | -2.190% | +4.243% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.462% | -0.079% | +27.418% | +9.978% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.348% | -0.556% | +2.623% | +7.517% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.640% | +0.184% | +12.957% | +10.543% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.117% | -0.394% | -3.323% | -0.421% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.498% | +0.054% | +4.938% | +4.163% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.088% | -0.330% | +6.541% | +6.964% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.356% | +0.096% | +6.808% | +4.451% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.277% | -0.402% | +19.459% | +6.148% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.276% | -0.490% | +11.088% | +9.340% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.891% | -0.518% | +8.993% | +7.896% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.378% | -1.097% | +10.600% | +9.524% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.355% | +0.120% | +9.970% | +11.105% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 5.742% | +0.453% | +19.407% | +13.868% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.137% | -0.519% | +5.572% | +7.404% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.984% | +0.833% | +2.382% | +2.502% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 9.275% | -2.460% | +2.381% | +22.251% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.747% | +0.730% | +0.239% | +15.877% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 3.508% | -0.169% | +2.676% | +10.408% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.898% | -0.261% | +5.656% | +9.569% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.508% | +0.253% | +3.862% | +8.968% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.651% | +0.425% | -6.963% | +13.189% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.384% | +0.314% | +7.122% | +9.560% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2017-12-12 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Tue Dec 12 19:39:30 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 13 Dec 2017 00:39:30 -0000 Subject: [Python-checkins] bpo-17852: Revert incorrect fix based on misunderstanding of _Py_PyAtExit() semantics (#4826) Message-ID: https://github.com/python/cpython/commit/317def9fdb29893df1ab380d396fcdd2eafe0588 commit: 317def9fdb29893df1ab380d396fcdd2eafe0588 branch: master author: Antoine Pitrou committer: Victor Stinner date: 2017-12-13T01:39:26+01:00 summary: bpo-17852: Revert incorrect fix based on misunderstanding of _Py_PyAtExit() semantics (#4826) files: A Misc/NEWS.d/next/Library/2017-12-13-00-00-37.bpo-17852.Q8BP8N.rst M Lib/_pyio.py M Modules/_io/_iomodule.c M Modules/_io/_iomodule.h M Modules/_io/bufferedio.c diff --git a/Lib/_pyio.py b/Lib/_pyio.py index adf5d0ecbf6..b59a6509787 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -1182,7 +1182,6 @@ def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): self.buffer_size = buffer_size self._write_buf = bytearray() self._write_lock = Lock() - _register_writer(self) def writable(self): return self.raw.writable() @@ -2587,26 +2586,3 @@ def encoding(self): def detach(self): # This doesn't make sense on StringIO. self._unsupported("detach") - - -# ____________________________________________________________ - -import atexit, weakref - -_all_writers = weakref.WeakSet() - -def _register_writer(w): - # keep weak-ref to buffered writer - _all_writers.add(w) - -def _flush_all_writers(): - # Ensure all buffered writers are flushed before proceeding with - # normal shutdown. Otherwise, if the underlying file objects get - # finalized before the buffered writer wrapping it then any buffered - # data will be lost. - for w in _all_writers: - try: - w.flush() - except: - pass -atexit.register(_flush_all_writers) diff --git a/Misc/NEWS.d/next/Library/2017-12-13-00-00-37.bpo-17852.Q8BP8N.rst b/Misc/NEWS.d/next/Library/2017-12-13-00-00-37.bpo-17852.Q8BP8N.rst new file mode 100644 index 00000000000..768108d5a54 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-13-00-00-37.bpo-17852.Q8BP8N.rst @@ -0,0 +1 @@ +Revert incorrect fix based on misunderstanding of _Py_PyAtExit() semantics. diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 5db44f970d2..f0621f4d4ab 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -766,8 +766,6 @@ PyInit__io(void) !(_PyIO_empty_bytes = PyBytes_FromStringAndSize(NULL, 0))) goto fail; - _Py_PyAtExit(_PyIO_atexit_flush); - state->initialized = 1; return m; diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 1dce5dada4e..db8403774ea 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -183,5 +183,3 @@ extern PyObject *_PyIO_empty_str; extern PyObject *_PyIO_empty_bytes; extern PyTypeObject _PyBytesIOBuffer_Type; - -extern void _PyIO_atexit_flush(void); diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 1ae7a70bbda..d7e82b9dba1 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -197,7 +197,7 @@ bufferediobase_write(PyObject *self, PyObject *args) } -typedef struct _buffered { +typedef struct { PyObject_HEAD PyObject *raw; @@ -239,18 +239,8 @@ typedef struct _buffered { PyObject *dict; PyObject *weakreflist; - - /* a doubly-linked chained list of "buffered" objects that need to - be flushed when the process exits */ - struct _buffered *next, *prev; } buffered; -/* the actual list of buffered objects */ -static buffered buffer_list_end = { - .next = &buffer_list_end, - .prev = &buffer_list_end -}; - /* Implementation notes: @@ -389,21 +379,10 @@ _enter_buffered_busy(buffered *self) (self->buffer_size * (size / self->buffer_size))) -static void -remove_from_linked_list(buffered *self) -{ - self->next->prev = self->prev; - self->prev->next = self->next; - self->prev = NULL; - self->next = NULL; -} - static void buffered_dealloc(buffered *self) { self->finalizing = 1; - if (self->next != NULL) - remove_from_linked_list(self); if (_PyIOBase_finalize((PyObject *) self) < 0) return; _PyObject_GC_UNTRACK(self); @@ -1827,38 +1806,10 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type && Py_TYPE(raw) == &PyFileIO_Type); - if (self->next == NULL) { - self->prev = &buffer_list_end; - self->next = buffer_list_end.next; - buffer_list_end.next->prev = self; - buffer_list_end.next = self; - } - self->ok = 1; return 0; } -/* -* Ensure all buffered writers are flushed before proceeding with -* normal shutdown. Otherwise, if the underlying file objects get -* finalized before the buffered writer wrapping it then any buffered -* data will be lost. -*/ -void _PyIO_atexit_flush(void) -{ - while (buffer_list_end.next != &buffer_list_end) { - buffered *buf = buffer_list_end.next; - remove_from_linked_list(buf); - if (buf->ok && !buf->finalizing) { - /* good state and not finalizing */ - Py_INCREF(buf); - buffered_flush(buf, NULL); - Py_DECREF(buf); - PyErr_Clear(); - } - } -} - static Py_ssize_t _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len) { From webhook-mailer at python.org Tue Dec 12 20:29:13 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Wed, 13 Dec 2017 01:29:13 -0000 Subject: [Python-checkins] Test atexit shutdown mechanism in a subprocess (#4828) Message-ID: https://github.com/python/cpython/commit/fc5db95e0063eafa2bfb7f487fcaad5a7c4b65a1 commit: fc5db95e0063eafa2bfb7f487fcaad5a7c4b65a1 branch: master author: Antoine Pitrou committer: GitHub date: 2017-12-13T02:29:07+01:00 summary: Test atexit shutdown mechanism in a subprocess (#4828) * Test atexit shutdown mechanism in a subprocess files: M Lib/test/test_atexit.py M Python/pylifecycle.c diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py index 1d0b018aafa..aa56388ef60 100644 --- a/Lib/test/test_atexit.py +++ b/Lib/test/test_atexit.py @@ -3,6 +3,7 @@ import io import atexit from test import support +from test.support import script_helper ### helpers def h1(): @@ -152,6 +153,21 @@ def test_bound_methods(self): atexit._run_exitfuncs() self.assertEqual(l, [5]) + def test_shutdown(self): + # Actually test the shutdown mechanism in a subprocess + code = """if 1: + import atexit + + def f(msg): + print(msg) + + atexit.register(f, "one") + atexit.register(f, "two") + """ + res = script_helper.assert_python_ok("-c", code) + self.assertEqual(res.out.decode().splitlines(), ["two", "one"]) + self.assertFalse(res.err) + @support.cpython_only class SubinterpreterTest(unittest.TestCase): diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index fdb09d910da..f284855f342 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2086,6 +2086,8 @@ _Py_FatalInitError(_PyInitError err) /* For the atexit module. */ void _Py_PyAtExit(void (*func)(void)) { + /* Guard against API misuse (see bpo-17852) */ + assert(_PyRuntime.pyexitfunc == NULL || _PyRuntime.pyexitfunc == func); _PyRuntime.pyexitfunc = func; } From webhook-mailer at python.org Wed Dec 13 03:40:02 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 13 Dec 2017 08:40:02 -0000 Subject: [Python-checkins] bpo-32284: Fix documentation of BinaryIO and TextIO (#4832) Message-ID: https://github.com/python/cpython/commit/c3e070f84931c847d1b35e7fb36aa71edd6215f6 commit: c3e070f84931c847d1b35e7fb36aa71edd6215f6 branch: master author: Sebastian Rittau committer: Andrew Svetlov date: 2017-12-13T10:39:55+02:00 summary: bpo-32284: Fix documentation of BinaryIO and TextIO (#4832) files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index d28a5d54843..9c4777ac2fe 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -774,9 +774,9 @@ The module defines the following classes, functions and decorators: Wrapper namespace for I/O stream types. - This defines the generic type ``IO[AnyStr]`` and aliases ``TextIO`` - and ``BinaryIO`` for respectively ``IO[str]`` and ``IO[bytes]``. - These represent the types of I/O streams such as returned by + This defines the generic type ``IO[AnyStr]`` and subclasses ``TextIO`` + and ``BinaryIO``, deriving from ``IO[str]`` and ``IO[bytes]``, + respectively. These represent the types of I/O streams such as returned by :func:`open`. These types are also accessible directly as ``typing.IO``, From webhook-mailer at python.org Wed Dec 13 03:59:08 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 13 Dec 2017 08:59:08 -0000 Subject: [Python-checkins] bpo-32284: Fix documentation of BinaryIO and TextIO (GH-4832) (#4833) Message-ID: https://github.com/python/cpython/commit/b0358e8784821867ab05b3d890717c37309be849 commit: b0358e8784821867ab05b3d890717c37309be849 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-13T10:59:01+02:00 summary: bpo-32284: Fix documentation of BinaryIO and TextIO (GH-4832) (#4833) (cherry picked from commit c3e070f84931c847d1b35e7fb36aa71edd6215f6) files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index d28a5d54843..9c4777ac2fe 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -774,9 +774,9 @@ The module defines the following classes, functions and decorators: Wrapper namespace for I/O stream types. - This defines the generic type ``IO[AnyStr]`` and aliases ``TextIO`` - and ``BinaryIO`` for respectively ``IO[str]`` and ``IO[bytes]``. - These represent the types of I/O streams such as returned by + This defines the generic type ``IO[AnyStr]`` and subclasses ``TextIO`` + and ``BinaryIO``, deriving from ``IO[str]`` and ``IO[bytes]``, + respectively. These represent the types of I/O streams such as returned by :func:`open`. These types are also accessible directly as ``typing.IO``, From webhook-mailer at python.org Wed Dec 13 05:54:05 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Wed, 13 Dec 2017 10:54:05 -0000 Subject: [Python-checkins] [3.6] Test atexit shutdown mechanism in a subprocess (GH-4828) (#4829) Message-ID: https://github.com/python/cpython/commit/b6263ca313d9806a4b7f1a3a3441d54e6338cc94 commit: b6263ca313d9806a4b7f1a3a3441d54e6338cc94 branch: 3.6 author: Antoine Pitrou committer: GitHub date: 2017-12-13T11:53:59+01:00 summary: [3.6] Test atexit shutdown mechanism in a subprocess (GH-4828) (#4829) * Test atexit shutdown mechanism in a subprocess. (cherry picked from commit fc5db95e0063eafa2bfb7f487fcaad5a7c4b65a1) files: M Lib/test/test_atexit.py diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py index 1d0b018aafa..aa56388ef60 100644 --- a/Lib/test/test_atexit.py +++ b/Lib/test/test_atexit.py @@ -3,6 +3,7 @@ import io import atexit from test import support +from test.support import script_helper ### helpers def h1(): @@ -152,6 +153,21 @@ def test_bound_methods(self): atexit._run_exitfuncs() self.assertEqual(l, [5]) + def test_shutdown(self): + # Actually test the shutdown mechanism in a subprocess + code = """if 1: + import atexit + + def f(msg): + print(msg) + + atexit.register(f, "one") + atexit.register(f, "two") + """ + res = script_helper.assert_python_ok("-c", code) + self.assertEqual(res.out.decode().splitlines(), ["two", "one"]) + self.assertFalse(res.err) + @support.cpython_only class SubinterpreterTest(unittest.TestCase): From webhook-mailer at python.org Wed Dec 13 06:29:12 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 13 Dec 2017 11:29:12 -0000 Subject: [Python-checkins] bpo-29240: PEP 540: Add a new UTF-8 Mode (#855) Message-ID: https://github.com/python/cpython/commit/91106cd9ff2f321c0f60fbaa09fd46c80aa5c266 commit: 91106cd9ff2f321c0f60fbaa09fd46c80aa5c266 branch: master author: Victor Stinner committer: GitHub date: 2017-12-13T12:29:09+01:00 summary: bpo-29240: PEP 540: Add a new UTF-8 Mode (#855) * Add -X utf8 command line option, PYTHONUTF8 environment variable and a new sys.flags.utf8_mode flag. * If the LC_CTYPE locale is "C" at startup: enable automatically the UTF-8 mode. * Add _winapi.GetACP(). encodings._alias_mbcs() now calls _winapi.GetACP() to get the ANSI code page * locale.getpreferredencoding() now returns 'UTF-8' in the UTF-8 mode. As a side effect, open() now uses the UTF-8 encoding by default in this mode. * Py_DecodeLocale() and Py_EncodeLocale() now use the UTF-8 encoding in the UTF-8 Mode. * Update subprocess._args_from_interpreter_flags() to handle -X utf8 * Skip some tests relying on the current locale if the UTF-8 mode is enabled. * Add test_utf8mode.py. * _Py_DecodeUTF8_surrogateescape() gets a new optional parameter to return also the length (number of wide characters). * pymain_get_global_config() and pymain_set_global_config() now always copy flag values, rather than only copying if the new value is greater than the old value. files: A Lib/test/test_utf8_mode.py A Misc/NEWS.d/next/Core and Builtins/2017-12-05-23-10-58.bpo-29240.qpJP5l.rst M Doc/c-api/sys.rst M Doc/library/locale.rst M Doc/library/sys.rst M Doc/using/cmdline.rst M Doc/whatsnew/3.7.rst M Include/fileobject.h M Include/pystate.h M Lib/_bootlocale.py M Lib/encodings/__init__.py M Lib/locale.py M Lib/subprocess.py M Lib/test/test_builtin.py M Lib/test/test_c_locale_coercion.py M Lib/test/test_codecs.py M Lib/test/test_io.py M Lib/test/test_sys.py M Modules/_winapi.c M Modules/clinic/_winapi.c.h M Modules/main.c M Objects/unicodeobject.c M Programs/python.c M Python/bltinmodule.c M Python/fileutils.c M Python/pylifecycle.c M Python/sysmodule.c diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst index 95d9d657ce9..20bc7bd3df3 100644 --- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -127,6 +127,9 @@ Operating System Utilities .. versionadded:: 3.5 + .. versionchanged:: 3.7 + The function now uses the UTF-8 encoding in the UTF-8 mode. + .. c:function:: char* Py_EncodeLocale(const wchar_t *text, size_t *error_pos) @@ -138,12 +141,15 @@ Operating System Utilities to free the memory. Return ``NULL`` on encoding error or memory allocation error - If error_pos is not ``NULL``, ``*error_pos`` is set to the index of the - invalid character on encoding error, or set to ``(size_t)-1`` otherwise. + If error_pos is not ``NULL``, ``*error_pos`` is set to ``(size_t)-1`` on + success, or set to the index of the invalid character on encoding error. Use the :c:func:`Py_DecodeLocale` function to decode the bytes string back to a wide character string. + .. versionchanged:: 3.7 + The function now uses the UTF-8 encoding in the UTF-8 mode. + .. seealso:: The :c:func:`PyUnicode_EncodeFSDefault` and @@ -151,6 +157,9 @@ Operating System Utilities .. versionadded:: 3.5 + .. versionchanged:: 3.7 + The function now supports the UTF-8 mode. + .. _systemfunctions: diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst index e8567a7b658..7da94a23964 100644 --- a/Doc/library/locale.rst +++ b/Doc/library/locale.rst @@ -316,6 +316,13 @@ The :mod:`locale` module defines the following exception and functions: preferences, so this function is not thread-safe. If invoking setlocale is not necessary or desired, *do_setlocale* should be set to ``False``. + On Android or in the UTF-8 mode (:option:`-X` ``utf8`` option), always + return ``'UTF-8'``, the locale and the *do_setlocale* argument are ignored. + + .. versionchanged:: 3.7 + The function now always returns ``UTF-8`` on Android or if the UTF-8 mode + is enabled. + .. function:: normalize(localename) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 9e47681804b..957d02b2a30 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -313,6 +313,9 @@ always available. has caught :exc:`SystemExit` (such as an error flushing buffered data in the standard streams), the exit status is changed to 120. + .. versionchanged:: 3.7 + Added ``utf8_mode`` attribute for the new :option:`-X` ``utf8`` flag. + .. data:: flags @@ -335,6 +338,7 @@ always available. :const:`quiet` :option:`-q` :const:`hash_randomization` :option:`-R` :const:`dev_mode` :option:`-X` ``dev`` + :const:`utf8_mode` :option:`-X` ``utf8`` ============================= ============================= .. versionchanged:: 3.2 @@ -347,7 +351,8 @@ always available. Removed obsolete ``division_warning`` attribute. .. versionchanged:: 3.7 - Added ``dev_mode`` attribute for the new :option:`-X` ``dev`` flag. + Added ``dev_mode`` attribute for the new :option:`-X` ``dev`` flag + and ``utf8_mode`` attribute for the new :option:`-X` ``utf8`` flag. .. data:: float_info @@ -492,6 +497,8 @@ always available. :func:`os.fsencode` and :func:`os.fsdecode` should be used to ensure that the correct encoding and errors mode are used. + * In the UTF-8 mode, the encoding is ``utf-8`` on any platform. + * On Mac OS X, the encoding is ``'utf-8'``. * On Unix, the encoding is the locale encoding. @@ -506,6 +513,10 @@ always available. Windows is no longer guaranteed to return ``'mbcs'``. See :pep:`529` and :func:`_enablelegacywindowsfsencoding` for more information. + .. versionchanged:: 3.7 + Return 'utf-8' in the UTF-8 mode. + + .. function:: getfilesystemencodeerrors() Return the name of the error mode used to convert between Unicode filenames diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index e32f77e7ffc..5cb90717705 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -439,6 +439,9 @@ Miscellaneous options * Set the :attr:`~sys.flags.dev_mode` attribute of :attr:`sys.flags` to ``True`` + * ``-X utf8`` enables the UTF-8 mode, whereas ``-X utf8=0`` disables the + UTF-8 mode. + It also allows passing arbitrary values and retrieving them through the :data:`sys._xoptions` dictionary. @@ -455,7 +458,7 @@ Miscellaneous options The ``-X showalloccount`` option. .. versionadded:: 3.7 - The ``-X importtime`` and ``-X dev`` options. + The ``-X importtime``, ``-X dev`` and ``-X utf8`` options. Options you shouldn't use @@ -816,6 +819,14 @@ conflict. .. versionadded:: 3.7 +.. envvar:: PYTHONUTF8 + + If set to ``1``, enable the UTF-8 mode. If set to ``0``, disable the UTF-8 + mode. Any other non-empty string cause an error. + + .. versionadded:: 3.7 + + Debug-mode variables ~~~~~~~~~~~~~~~~~~~~ diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 58bfaef282c..81a88a0c82e 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -185,6 +185,23 @@ resolution on Linux and Windows. PEP written and implemented by Victor Stinner +PEP 540: Add a new UTF-8 mode +----------------------------- + +Add a new UTF-8 mode to ignore the locale, use the UTF-8 encoding, and change +:data:`sys.stdin` and :data:`sys.stdout` error handlers to ``surrogateescape``. +This mode is enabled by default in the POSIX locale, but otherwise disabled by +default. + +The new :option:`-X` ``utf8`` command line option and :envvar:`PYTHONUTF8` +environment variable are added to control the UTF-8 mode. + +.. seealso:: + + :pep:`540` -- Add a new UTF-8 mode + PEP written and implemented by Victor Stinner + + New Development Mode: -X dev ---------------------------- @@ -353,6 +370,10 @@ Added another argument *monetary* in :meth:`format_string` of :mod:`locale`. If *monetary* is true, the conversion uses monetary thousands separator and grouping strings. (Contributed by Garvit in :issue:`10379`.) +The :func:`locale.getpreferredencoding` function now always returns ``'UTF-8'`` +on Android or in the UTF-8 mode (:option:`-X` ``utf8`` option), the locale and +the *do_setlocale* argument are ignored. + math ---- diff --git a/Include/fileobject.h b/Include/fileobject.h index 0b1678ee8da..89e8dd6a285 100644 --- a/Include/fileobject.h +++ b/Include/fileobject.h @@ -28,6 +28,10 @@ PyAPI_DATA(const char *) Py_FileSystemDefaultEncodeErrors; #endif PyAPI_DATA(int) Py_HasFileSystemDefaultEncoding; +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 +PyAPI_DATA(int) Py_UTF8Mode; +#endif + /* Internal API The std printer acts as a preliminary sys.stderr until the new io diff --git a/Include/pystate.h b/Include/pystate.h index d149aeb2aff..c7ea179cf7d 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -38,6 +38,7 @@ typedef struct { int show_alloc_count; /* -X showalloccount */ int dump_refs; /* PYTHONDUMPREFS */ int malloc_stats; /* PYTHONMALLOCSTATS */ + int utf8_mode; /* -X utf8 or PYTHONUTF8 environment variable */ } _PyCoreConfig; #define _PyCoreConfig_INIT (_PyCoreConfig){.use_hash_seed = -1} diff --git a/Lib/_bootlocale.py b/Lib/_bootlocale.py index 0c61b0d3a0f..3273a3b4225 100644 --- a/Lib/_bootlocale.py +++ b/Lib/_bootlocale.py @@ -9,6 +9,8 @@ if sys.platform.startswith("win"): def getpreferredencoding(do_setlocale=True): + if sys.flags.utf8_mode: + return 'UTF-8' return _locale._getdefaultlocale()[1] else: try: @@ -21,6 +23,8 @@ def getpreferredencoding(do_setlocale=True): return 'UTF-8' else: def getpreferredencoding(do_setlocale=True): + if sys.flags.utf8_mode: + return 'UTF-8' # This path for legacy systems needs the more complex # getdefaultlocale() function, import the full locale module. import locale @@ -28,6 +32,8 @@ def getpreferredencoding(do_setlocale=True): else: def getpreferredencoding(do_setlocale=True): assert not do_setlocale + if sys.flags.utf8_mode: + return 'UTF-8' result = _locale.nl_langinfo(_locale.CODESET) if not result and sys.platform == 'darwin': # nl_langinfo can return an empty string diff --git a/Lib/encodings/__init__.py b/Lib/encodings/__init__.py index aa2fb7c2b93..025b7a8da3d 100644 --- a/Lib/encodings/__init__.py +++ b/Lib/encodings/__init__.py @@ -158,8 +158,9 @@ def search_function(encoding): if sys.platform == 'win32': def _alias_mbcs(encoding): try: - import _bootlocale - if encoding == _bootlocale.getpreferredencoding(False): + import _winapi + ansi_code_page = "cp%s" % _winapi.GetACP() + if encoding == ansi_code_page: import encodings.mbcs return encodings.mbcs.getregentry() except ImportError: diff --git a/Lib/locale.py b/Lib/locale.py index f1d157d6f9c..18079e73ad6 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -617,6 +617,8 @@ def resetlocale(category=LC_ALL): # On Win32, this will return the ANSI code page def getpreferredencoding(do_setlocale = True): """Return the charset that the user is likely using.""" + if sys.flags.utf8_mode: + return 'UTF-8' import _bootlocale return _bootlocale.getpreferredencoding(False) else: @@ -634,6 +636,8 @@ def getpreferredencoding(do_setlocale = True): def getpreferredencoding(do_setlocale = True): """Return the charset that the user is likely using, by looking at environment variables.""" + if sys.flags.utf8_mode: + return 'UTF-8' res = getdefaultlocale()[1] if res is None: # LANG not set, default conservatively to ASCII @@ -643,6 +647,8 @@ def getpreferredencoding(do_setlocale = True): def getpreferredencoding(do_setlocale = True): """Return the charset that the user is likely using, according to the system configuration.""" + if sys.flags.utf8_mode: + return 'UTF-8' import _bootlocale if do_setlocale: oldloc = setlocale(LC_CTYPE) diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 301433cdf5d..65b4086dc61 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -280,7 +280,7 @@ def _args_from_interpreter_flags(): if dev_mode: args.extend(('-X', 'dev')) for opt in ('faulthandler', 'tracemalloc', 'importtime', - 'showalloccount', 'showrefcount'): + 'showalloccount', 'showrefcount', 'utf8'): if opt in xoptions: value = xoptions[opt] if value is True: diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 0a61c054444..9329318706b 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1022,6 +1022,7 @@ def test_open(self): self.assertRaises(ValueError, open, 'a\x00b') self.assertRaises(ValueError, open, b'a\x00b') + @unittest.skipIf(sys.flags.utf8_mode, "utf-8 mode is enabled") def test_open_default_encoding(self): old_environ = dict(os.environ) try: diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 2a22739fb0f..c0845d75a29 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -130,7 +130,7 @@ def get_child_details(cls, env_vars): that. """ result, py_cmd = run_python_until_end( - "-c", cls.CHILD_PROCESS_SCRIPT, + "-X", "utf8=0", "-c", cls.CHILD_PROCESS_SCRIPT, __isolated=True, **env_vars ) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index eb21a3915b9..a59a5e21358 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -5,6 +5,7 @@ import sys import unittest import encodings +from unittest import mock from test import support @@ -3180,16 +3181,9 @@ def test_incremental(self): def test_mbcs_alias(self): # Check that looking up our 'default' codepage will return # mbcs when we don't have a more specific one available - import _bootlocale - def _get_fake_codepage(*a): - return 'cp123' - old_getpreferredencoding = _bootlocale.getpreferredencoding - _bootlocale.getpreferredencoding = _get_fake_codepage - try: + with mock.patch('_winapi.GetACP', return_value=123): codec = codecs.lookup('cp123') self.assertEqual(codec.name, 'mbcs') - finally: - _bootlocale.getpreferredencoding = old_getpreferredencoding class ASCIITest(unittest.TestCase): diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 6bb4127b095..66748317b5f 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2580,6 +2580,7 @@ def test_reconfigure_line_buffering(self): t.reconfigure(line_buffering=None) self.assertEqual(t.line_buffering, True) + @unittest.skipIf(sys.flags.utf8_mode, "utf-8 mode is enabled") def test_default_encoding(self): old_environ = dict(os.environ) try: @@ -2599,6 +2600,7 @@ def test_default_encoding(self): os.environ.update(old_environ) @support.cpython_only + @unittest.skipIf(sys.flags.utf8_mode, "utf-8 mode is enabled") def test_device_encoding(self): # Issue 15989 import _testcapi diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 6346094ad08..6933b41353b 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -527,7 +527,7 @@ def test_sys_flags(self): "inspect", "interactive", "optimize", "dont_write_bytecode", "no_user_site", "no_site", "ignore_environment", "verbose", "bytes_warning", "quiet", "hash_randomization", "isolated", - "dev_mode") + "dev_mode", "utf8_mode") for attr in attrs: self.assertTrue(hasattr(sys.flags, attr), attr) attr_type = bool if attr == "dev_mode" else int @@ -535,6 +535,8 @@ def test_sys_flags(self): self.assertTrue(repr(sys.flags)) self.assertEqual(len(sys.flags), len(attrs)) + self.assertIn(sys.flags.utf8_mode, {0, 1, 2}) + def assert_raise_on_new_sys_type(self, sys_attr): # Users are intentionally prevented from creating new instances of # sys.flags, sys.version_info, and sys.getwindowsversion. @@ -710,8 +712,8 @@ def test_c_locale_surrogateescape(self): # have no any effect out = self.c_locale_get_error_handler(encoding=':') self.assertEqual(out, - 'stdin: surrogateescape\n' - 'stdout: surrogateescape\n' + 'stdin: strict\n' + 'stdout: strict\n' 'stderr: backslashreplace\n') out = self.c_locale_get_error_handler(encoding='') self.assertEqual(out, diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py new file mode 100644 index 00000000000..275a6ea8ed6 --- /dev/null +++ b/Lib/test/test_utf8_mode.py @@ -0,0 +1,206 @@ +""" +Test the implementation of the PEP 540: the UTF-8 Mode. +""" + +import locale +import os +import sys +import textwrap +import unittest +from test.support.script_helper import assert_python_ok, assert_python_failure + + +MS_WINDOWS = (sys.platform == 'win32') + + +class UTF8ModeTests(unittest.TestCase): + # Override PYTHONUTF8 and PYTHONLEGACYWINDOWSFSENCODING environment + # variables by default + DEFAULT_ENV = {'PYTHONUTF8': '', 'PYTHONLEGACYWINDOWSFSENCODING': ''} + + def posix_locale(self): + loc = locale.setlocale(locale.LC_CTYPE, None) + return (loc == 'C') + + def get_output(self, *args, failure=False, **kw): + kw = dict(self.DEFAULT_ENV, **kw) + if failure: + out = assert_python_failure(*args, **kw) + out = out[2] + else: + out = assert_python_ok(*args, **kw) + out = out[1] + return out.decode().rstrip("\n\r") + + @unittest.skipIf(MS_WINDOWS, 'Windows has no POSIX locale') + def test_posix_locale(self): + code = 'import sys; print(sys.flags.utf8_mode)' + + out = self.get_output('-c', code, LC_ALL='C') + self.assertEqual(out, '1') + + def test_xoption(self): + code = 'import sys; print(sys.flags.utf8_mode)' + + out = self.get_output('-X', 'utf8', '-c', code) + self.assertEqual(out, '1') + + # undocumented but accepted syntax: -X utf8=1 + out = self.get_output('-X', 'utf8=1', '-c', code) + self.assertEqual(out, '1') + + out = self.get_output('-X', 'utf8=0', '-c', code) + self.assertEqual(out, '0') + + if MS_WINDOWS: + # PYTHONLEGACYWINDOWSFSENCODING disables the UTF-8 + # and has the priority over -X utf8 + out = self.get_output('-X', 'utf8', '-c', code, + PYTHONLEGACYWINDOWSFSENCODING='1') + self.assertEqual(out, '0') + + def test_env_var(self): + code = 'import sys; print(sys.flags.utf8_mode)' + + out = self.get_output('-c', code, PYTHONUTF8='1') + self.assertEqual(out, '1') + + out = self.get_output('-c', code, PYTHONUTF8='0') + self.assertEqual(out, '0') + + # -X utf8 has the priority over PYTHONUTF8 + out = self.get_output('-X', 'utf8=0', '-c', code, PYTHONUTF8='1') + self.assertEqual(out, '0') + + if MS_WINDOWS: + # PYTHONLEGACYWINDOWSFSENCODING disables the UTF-8 mode + # and has the priority over PYTHONUTF8 + out = self.get_output('-X', 'utf8', '-c', code, PYTHONUTF8='1', + PYTHONLEGACYWINDOWSFSENCODING='1') + self.assertEqual(out, '0') + + # Cannot test with the POSIX locale, since the POSIX locale enables + # the UTF-8 mode + if not self.posix_locale(): + # PYTHONUTF8 should be ignored if -E is used + out = self.get_output('-E', '-c', code, PYTHONUTF8='1') + self.assertEqual(out, '0') + + # invalid mode + out = self.get_output('-c', code, PYTHONUTF8='xxx', failure=True) + self.assertIn('invalid PYTHONUTF8 environment variable value', + out.rstrip()) + + def test_filesystemencoding(self): + code = textwrap.dedent(''' + import sys + print("{}/{}".format(sys.getfilesystemencoding(), + sys.getfilesystemencodeerrors())) + ''') + + if MS_WINDOWS: + expected = 'utf-8/surrogatepass' + else: + expected = 'utf-8/surrogateescape' + + out = self.get_output('-X', 'utf8', '-c', code) + self.assertEqual(out, expected) + + if MS_WINDOWS: + # PYTHONLEGACYWINDOWSFSENCODING disables the UTF-8 mode + # and has the priority over -X utf8 and PYTHONUTF8 + out = self.get_output('-X', 'utf8', '-c', code, + PYTHONUTF8='strict', + PYTHONLEGACYWINDOWSFSENCODING='1') + self.assertEqual(out, 'mbcs/replace') + + def test_stdio(self): + code = textwrap.dedent(''' + import sys + print(f"stdin: {sys.stdin.encoding}/{sys.stdin.errors}") + print(f"stdout: {sys.stdout.encoding}/{sys.stdout.errors}") + print(f"stderr: {sys.stderr.encoding}/{sys.stderr.errors}") + ''') + + out = self.get_output('-X', 'utf8', '-c', code, + PYTHONIOENCODING='') + self.assertEqual(out.splitlines(), + ['stdin: utf-8/surrogateescape', + 'stdout: utf-8/surrogateescape', + 'stderr: utf-8/backslashreplace']) + + # PYTHONIOENCODING has the priority over PYTHONUTF8 + out = self.get_output('-X', 'utf8', '-c', code, + PYTHONIOENCODING="latin1") + self.assertEqual(out.splitlines(), + ['stdin: latin1/strict', + 'stdout: latin1/strict', + 'stderr: latin1/backslashreplace']) + + out = self.get_output('-X', 'utf8', '-c', code, + PYTHONIOENCODING=":namereplace") + self.assertEqual(out.splitlines(), + ['stdin: UTF-8/namereplace', + 'stdout: UTF-8/namereplace', + 'stderr: UTF-8/backslashreplace']) + + def test_io(self): + code = textwrap.dedent(''' + import sys + filename = sys.argv[1] + with open(filename) as fp: + print(f"{fp.encoding}/{fp.errors}") + ''') + filename = __file__ + + out = self.get_output('-c', code, filename, PYTHONUTF8='1') + self.assertEqual(out, 'UTF-8/strict') + + def _check_io_encoding(self, module, encoding=None, errors=None): + filename = __file__ + + # Encoding explicitly set + args = [] + if encoding: + args.append(f'encoding={encoding!r}') + if errors: + args.append(f'errors={errors!r}') + code = textwrap.dedent(''' + import sys + from %s import open + filename = sys.argv[1] + with open(filename, %s) as fp: + print(f"{fp.encoding}/{fp.errors}") + ''') % (module, ', '.join(args)) + out = self.get_output('-c', code, filename, + PYTHONUTF8='1') + + if not encoding: + encoding = 'UTF-8' + if not errors: + errors = 'strict' + self.assertEqual(out, f'{encoding}/{errors}') + + def check_io_encoding(self, module): + self._check_io_encoding(module, encoding="latin1") + self._check_io_encoding(module, errors="namereplace") + self._check_io_encoding(module, + encoding="latin1", errors="namereplace") + + def test_io_encoding(self): + self.check_io_encoding('io') + + def test_io_encoding(self): + self.check_io_encoding('_pyio') + + def test_locale_getpreferredencoding(self): + code = 'import locale; print(locale.getpreferredencoding(False), locale.getpreferredencoding(True))' + out = self.get_output('-X', 'utf8', '-c', code) + self.assertEqual(out, 'UTF-8 UTF-8') + + out = self.get_output('-X', 'utf8', '-c', code, LC_ALL='C') + self.assertEqual(out, 'UTF-8 UTF-8') + + +if __name__ == "__main__": + unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-05-23-10-58.bpo-29240.qpJP5l.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-05-23-10-58.bpo-29240.qpJP5l.rst new file mode 100644 index 00000000000..dbd9d619411 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-05-23-10-58.bpo-29240.qpJP5l.rst @@ -0,0 +1 @@ +Add a new UTF-8 mode: implementation of the :pep:`540`. diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 0a1d139cd0e..604c05d4ae1 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -1490,6 +1490,20 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer, } +/*[clinic input] +_winapi.GetACP + +Get the current Windows ANSI code page identifier. +[clinic start generated code]*/ + +static PyObject * +_winapi_GetACP_impl(PyObject *module) +/*[clinic end generated code: output=f7ee24bf705dbb88 input=1433c96d03a05229]*/ +{ + return PyLong_FromUnsignedLong(GetACP()); +} + + static PyMethodDef winapi_functions[] = { _WINAPI_CLOSEHANDLE_METHODDEF _WINAPI_CONNECTNAMEDPIPE_METHODDEF @@ -1515,6 +1529,7 @@ static PyMethodDef winapi_functions[] = { _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF _WINAPI_WAITFORSINGLEOBJECT_METHODDEF _WINAPI_WRITEFILE_METHODDEF + _WINAPI_GETACP_METHODDEF {NULL, NULL} }; @@ -1595,14 +1610,14 @@ PyInit__winapi(void) WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0); WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0); WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT); - + WINAPI_CONSTANT(F_DWORD, ABOVE_NORMAL_PRIORITY_CLASS); WINAPI_CONSTANT(F_DWORD, BELOW_NORMAL_PRIORITY_CLASS); WINAPI_CONSTANT(F_DWORD, HIGH_PRIORITY_CLASS); WINAPI_CONSTANT(F_DWORD, IDLE_PRIORITY_CLASS); WINAPI_CONSTANT(F_DWORD, NORMAL_PRIORITY_CLASS); WINAPI_CONSTANT(F_DWORD, REALTIME_PRIORITY_CLASS); - + WINAPI_CONSTANT(F_DWORD, CREATE_NO_WINDOW); WINAPI_CONSTANT(F_DWORD, DETACHED_PROCESS); WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE); diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h index 01bba360714..e5781efb938 100644 --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -889,4 +889,22 @@ _winapi_WriteFile(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject exit: return return_value; } -/*[clinic end generated code: output=fba2ad7bf1a87e4a input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_winapi_GetACP__doc__, +"GetACP($module, /)\n" +"--\n" +"\n" +"Get the current Windows ANSI code page identifier."); + +#define _WINAPI_GETACP_METHODDEF \ + {"GetACP", (PyCFunction)_winapi_GetACP, METH_NOARGS, _winapi_GetACP__doc__}, + +static PyObject * +_winapi_GetACP_impl(PyObject *module); + +static PyObject * +_winapi_GetACP(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _winapi_GetACP_impl(module); +} +/*[clinic end generated code: output=fd91c1ec286f0bf3 input=a9049054013a1b77]*/ diff --git a/Modules/main.c b/Modules/main.c index ac8a38c8f84..9ce111cea99 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1114,50 +1114,32 @@ pymain_set_argv(_PyMain *pymain) } -static void -pymain_get_flag(int flag, int *value) -{ - if (flag) { - *value = flag; - } -} - -static void -pymain_set_flag(int *flag, int value) -{ - /* Helper to set flag variables from command line options - * - uses the higher of the two values if they're both set - * - otherwise leaves the flag unset - */ - if (*flag < value) { - *flag = value; - } -} - - /* Get Py_xxx global configuration variables */ static void pymain_get_global_config(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; - pymain_get_flag(Py_BytesWarningFlag, &cmdline->bytes_warning); - pymain_get_flag(Py_DebugFlag, &cmdline->debug); - pymain_get_flag(Py_InspectFlag, &cmdline->inspect); - pymain_get_flag(Py_InteractiveFlag, &cmdline->interactive); - pymain_get_flag(Py_IsolatedFlag, &cmdline->isolated); - pymain_get_flag(Py_OptimizeFlag, &cmdline->optimization_level); - pymain_get_flag(Py_DontWriteBytecodeFlag, &cmdline->dont_write_bytecode); - pymain_get_flag(Py_NoUserSiteDirectory, &cmdline->no_user_site_directory); - pymain_get_flag(Py_NoSiteFlag, &cmdline->no_site_import); - pymain_get_flag(Py_UnbufferedStdioFlag, &cmdline->use_unbuffered_io); - pymain_get_flag(Py_VerboseFlag, &cmdline->verbosity); - pymain_get_flag(Py_QuietFlag, &cmdline->quiet_flag); + + cmdline->bytes_warning = Py_BytesWarningFlag; + cmdline->debug = Py_DebugFlag; + cmdline->inspect = Py_InspectFlag; + cmdline->interactive = Py_InteractiveFlag; + cmdline->isolated = Py_IsolatedFlag; + cmdline->optimization_level = Py_OptimizeFlag; + cmdline->dont_write_bytecode = Py_DontWriteBytecodeFlag; + cmdline->no_user_site_directory = Py_NoUserSiteDirectory; + cmdline->no_site_import = Py_NoSiteFlag; + cmdline->use_unbuffered_io = Py_UnbufferedStdioFlag; + cmdline->verbosity = Py_VerboseFlag; + cmdline->quiet_flag = Py_QuietFlag; #ifdef MS_WINDOWS - pymain_get_flag(Py_LegacyWindowsFSEncodingFlag, &cmdline->legacy_windows_fs_encoding); - pymain_get_flag(Py_LegacyWindowsStdioFlag, &cmdline->legacy_windows_stdio); + cmdline->legacy_windows_fs_encoding = Py_LegacyWindowsFSEncodingFlag; + cmdline->legacy_windows_stdio = Py_LegacyWindowsStdioFlag; #endif + cmdline->check_hash_pycs_mode = _Py_CheckHashBasedPycsMode ; - pymain_get_flag(Py_IgnoreEnvironmentFlag, &pymain->core_config.ignore_environment); + pymain->core_config.ignore_environment = Py_IgnoreEnvironmentFlag; + pymain->core_config.utf8_mode = Py_UTF8Mode; } @@ -1166,26 +1148,27 @@ static void pymain_set_global_config(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; - pymain_set_flag(&Py_BytesWarningFlag, cmdline->bytes_warning); - pymain_set_flag(&Py_DebugFlag, cmdline->debug); - pymain_set_flag(&Py_InspectFlag, cmdline->inspect); - pymain_set_flag(&Py_InteractiveFlag, cmdline->interactive); - pymain_set_flag(&Py_IsolatedFlag, cmdline->isolated); - pymain_set_flag(&Py_OptimizeFlag, cmdline->optimization_level); - pymain_set_flag(&Py_DontWriteBytecodeFlag, cmdline->dont_write_bytecode); - pymain_set_flag(&Py_NoUserSiteDirectory, cmdline->no_user_site_directory); - pymain_set_flag(&Py_NoSiteFlag, cmdline->no_site_import); - pymain_set_flag(&Py_UnbufferedStdioFlag, cmdline->use_unbuffered_io); - pymain_set_flag(&Py_VerboseFlag, cmdline->verbosity); - pymain_set_flag(&Py_QuietFlag, cmdline->quiet_flag); - if (cmdline->check_hash_pycs_mode) - _Py_CheckHashBasedPycsMode = cmdline->check_hash_pycs_mode; + + Py_BytesWarningFlag = cmdline->bytes_warning; + Py_DebugFlag = cmdline->debug; + Py_InspectFlag = cmdline->inspect; + Py_InteractiveFlag = cmdline->interactive; + Py_IsolatedFlag = cmdline->isolated; + Py_OptimizeFlag = cmdline->optimization_level; + Py_DontWriteBytecodeFlag = cmdline->dont_write_bytecode; + Py_NoUserSiteDirectory = cmdline->no_user_site_directory; + Py_NoSiteFlag = cmdline->no_site_import; + Py_UnbufferedStdioFlag = cmdline->use_unbuffered_io; + Py_VerboseFlag = cmdline->verbosity; + Py_QuietFlag = cmdline->quiet_flag; + _Py_CheckHashBasedPycsMode = cmdline->check_hash_pycs_mode; #ifdef MS_WINDOWS - pymain_set_flag(&Py_LegacyWindowsFSEncodingFlag, cmdline->legacy_windows_fs_encoding); - pymain_set_flag(&Py_LegacyWindowsStdioFlag, cmdline->legacy_windows_stdio); + Py_LegacyWindowsFSEncodingFlag = cmdline->legacy_windows_fs_encoding; + Py_LegacyWindowsStdioFlag = cmdline->legacy_windows_stdio; #endif - pymain_set_flag(&Py_IgnoreEnvironmentFlag, pymain->core_config.ignore_environment); + Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; + Py_UTF8Mode = pymain->core_config.utf8_mode; } @@ -1609,6 +1592,57 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) } +static int +pymain_init_utf8_mode(_PyMain *pymain) +{ + _PyCoreConfig *core_config = &pymain->core_config; + +#ifdef MS_WINDOWS + if (pymain->cmdline.legacy_windows_fs_encoding) { + core_config->utf8_mode = 0; + return 0; + } +#endif + + wchar_t *xopt = pymain_get_xoption(pymain, L"utf8"); + if (xopt) { + wchar_t *sep = wcschr(xopt, L'='); + if (sep) { + xopt = sep + 1; + if (wcscmp(xopt, L"1") == 0) { + core_config->utf8_mode = 1; + } + else if (wcscmp(xopt, L"0") == 0) { + core_config->utf8_mode = 0; + } + else { + pymain->err = _Py_INIT_USER_ERR("invalid -X utf8 option value"); + return -1; + } + } + else { + core_config->utf8_mode = 1; + } + return 0; + } + + char *opt = pymain_get_env_var("PYTHONUTF8"); + if (opt) { + if (strcmp(opt, "1") == 0) { + core_config->utf8_mode = 1; + } + else if (strcmp(opt, "0") == 0) { + core_config->utf8_mode = 0; + } + else { + pymain->err = _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment " + "variable value"); + return -1; + } + return 0; + } + return 0; +} static int @@ -1674,6 +1708,9 @@ pymain_parse_envvars(_PyMain *pymain) pymain->core_config.malloc_stats = 1; } + if (pymain_init_utf8_mode(pymain) < 0) { + return -1; + } return 0; } @@ -1702,6 +1739,7 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) if (pymain_parse_envvars(pymain) < 0) { return -1; } + /* FIXME: if utf8_mode value changed, parse again cmdline */ _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config); if (_Py_INIT_FAILED(err)) { @@ -1730,6 +1768,7 @@ pymain_parse_cmdline_envvars(_PyMain *pymain) static int pymain_init_python(_PyMain *pymain) { + pymain_set_global_config(pymain); pymain_init_stdio(pymain); @@ -1788,6 +1827,7 @@ pymain_init(_PyMain *pymain) return -1; } + pymain->core_config.utf8_mode = Py_UTF8Mode; pymain->core_config._disable_importlib = 0; pymain->config.install_signal_handlers = 1; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 8d4fea8ede1..c7480a0d87c 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5079,16 +5079,17 @@ PyUnicode_DecodeUTF8Stateful(const char *s, return NULL; } -#if defined(__APPLE__) || defined(__ANDROID__) -/* Simplified UTF-8 decoder using surrogateescape error handler, - used to decode the command line arguments on Mac OS X and Android. +/* UTF-8 decoder using the surrogateescape error handler . - Return a pointer to a newly allocated wide character string (use - PyMem_RawFree() to free the memory), or NULL on memory allocation error. */ + On success, return a pointer to a newly allocated wide character string (use + PyMem_RawFree() to free the memory) and write the output length (in number + of wchar_t units) into *p_wlen (if p_wlen is set). + On memory allocation failure, return -1 and write (size_t)-1 into *p_wlen + (if p_wlen is set). */ wchar_t* -_Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size) +_Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size, size_t *p_wlen) { const char *e; wchar_t *unicode; @@ -5096,11 +5097,20 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size) /* Note: size will always be longer than the resulting Unicode character count */ - if (PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t) < (size + 1)) + if (PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t) < (size + 1)) { + if (p_wlen) { + *p_wlen = (size_t)-1; + } return NULL; + } + unicode = PyMem_RawMalloc((size + 1) * sizeof(wchar_t)); - if (!unicode) + if (!unicode) { + if (p_wlen) { + *p_wlen = (size_t)-1; + } return NULL; + } /* Unpack UTF-8 encoded data */ e = s + size; @@ -5130,10 +5140,12 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size) } } unicode[outpos] = L'\0'; + if (p_wlen) { + *p_wlen = outpos; + } return unicode; } -#endif /* __APPLE__ or __ANDROID__ */ /* Primary internal function which creates utf8 encoded bytes objects. diff --git a/Programs/python.c b/Programs/python.c index 22d55bbc4ce..aef7122517a 100644 --- a/Programs/python.c +++ b/Programs/python.c @@ -17,6 +17,15 @@ wmain(int argc, wchar_t **argv) #else +static void _Py_NO_RETURN +fatal_error(const char *msg) +{ + fprintf(stderr, "Fatal Python error: %s\n", msg); + fflush(stderr); + exit(1); +} + + int main(int argc, char **argv) { @@ -28,9 +37,7 @@ main(int argc, char **argv) _PyInitError err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(err)) { - fprintf(stderr, "Fatal Python error: %s\n", err.msg); - fflush(stderr); - exit(1); + fatal_error(err.msg); } /* Force default allocator, to be able to release memory above @@ -40,7 +47,7 @@ main(int argc, char **argv) argv_copy = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1)); argv_copy2 = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1)); if (!argv_copy || !argv_copy2) { - fprintf(stderr, "out of memory\n"); + fatal_error("out of memory"); return 1; } @@ -55,7 +62,7 @@ main(int argc, char **argv) oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); if (!oldloc) { - fprintf(stderr, "out of memory\n"); + fatal_error("out of memory"); return 1; } @@ -73,6 +80,7 @@ main(int argc, char **argv) * details. */ if (_Py_LegacyLocaleDetected()) { + Py_UTF8Mode = 1; _Py_CoerceLegacyLocale(); } @@ -81,10 +89,7 @@ main(int argc, char **argv) argv_copy[i] = Py_DecodeLocale(argv[i], NULL); if (!argv_copy[i]) { PyMem_RawFree(oldloc); - fprintf(stderr, "Fatal Python error: " - "unable to decode the command line argument #%i\n", - i + 1); - return 1; + fatal_error("unable to decode the command line arguments"); } argv_copy2[i] = argv_copy[i]; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 81774dc5f8e..23d7aa45683 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -29,6 +29,9 @@ const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ int Py_HasFileSystemDefaultEncoding = 0; #endif const char *Py_FileSystemDefaultEncodeErrors = "surrogateescape"; +/* UTF-8 mode (PEP 540): if non-zero, use the UTF-8 encoding, and change stdin + and stdout error handler to "surrogateescape". */ +int Py_UTF8Mode = 0; _Py_IDENTIFIER(__builtins__); _Py_IDENTIFIER(__dict__); diff --git a/Python/fileutils.c b/Python/fileutils.c index eab58c50561..03cc37958a0 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -20,9 +20,8 @@ extern int winerror_to_errno(int); #include #endif /* HAVE_FCNTL_H */ -#if defined(__APPLE__) || defined(__ANDROID__) -extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size); -#endif +extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size, + size_t *p_wlen); #ifdef O_CLOEXEC /* Does open() support the O_CLOEXEC flag? Possible values: @@ -250,40 +249,9 @@ decode_ascii_surrogateescape(const char *arg, size_t *size) } #endif - -/* Decode a byte string from the locale encoding with the - surrogateescape error handler: undecodable bytes are decoded as characters - in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate - character, escape the bytes using the surrogateescape error handler instead - of decoding them. - - Return a pointer to a newly allocated wide character string, use - PyMem_RawFree() to free the memory. If size is not NULL, write the number of - wide characters excluding the null character into *size - - Return NULL on decoding error or memory allocation error. If *size* is not - NULL, *size is set to (size_t)-1 on memory error or set to (size_t)-2 on - decoding error. - - Decoding errors should never happen, unless there is a bug in the C - library. - - Use the Py_EncodeLocale() function to encode the character string back to a - byte string. */ -wchar_t* -Py_DecodeLocale(const char* arg, size_t *size) +static wchar_t* +decode_locale(const char* arg, size_t *size) { -#if defined(__APPLE__) || defined(__ANDROID__) - wchar_t *wstr; - wstr = _Py_DecodeUTF8_surrogateescape(arg, strlen(arg)); - if (size != NULL) { - if (wstr != NULL) - *size = wcslen(wstr); - else - *size = (size_t)-1; - } - return wstr; -#else wchar_t *res; size_t argsize; size_t count; @@ -293,19 +261,6 @@ Py_DecodeLocale(const char* arg, size_t *size) mbstate_t mbs; #endif -#ifndef MS_WINDOWS - if (force_ascii == -1) - force_ascii = check_force_ascii(); - - if (force_ascii) { - /* force ASCII encoding to workaround mbstowcs() issue */ - res = decode_ascii_surrogateescape(arg, size); - if (res == NULL) - goto oom; - return res; - } -#endif - #ifdef HAVE_BROKEN_MBSTOWCS /* Some platforms have a broken implementation of * mbstowcs which does not count the characters that @@ -402,43 +357,84 @@ Py_DecodeLocale(const char* arg, size_t *size) goto oom; #endif /* HAVE_MBRTOWC */ return res; + oom: - if (size != NULL) + if (size != NULL) { *size = (size_t)-1; + } return NULL; -#endif /* __APPLE__ or __ANDROID__ */ } -/* Encode a wide character string to the locale encoding with the - surrogateescape error handler: surrogate characters in the range - U+DC80..U+DCFF are converted to bytes 0x80..0xFF. - Return a pointer to a newly allocated byte string, use PyMem_Free() to free - the memory. Return NULL on encoding or memory allocation error. +/* Decode a byte string from the locale encoding with the + surrogateescape error handler: undecodable bytes are decoded as characters + in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate + character, escape the bytes using the surrogateescape error handler instead + of decoding them. - If error_pos is not NULL, *error_pos is set to the index of the invalid - character on encoding error, or set to (size_t)-1 otherwise. + Return a pointer to a newly allocated wide character string, use + PyMem_RawFree() to free the memory. If size is not NULL, write the number of + wide characters excluding the null character into *size - Use the Py_DecodeLocale() function to decode the bytes string back to a wide - character string. */ -char* -Py_EncodeLocale(const wchar_t *text, size_t *error_pos) + Return NULL on decoding error or memory allocation error. If *size* is not + NULL, *size is set to (size_t)-1 on memory error or set to (size_t)-2 on + decoding error. + + Decoding errors should never happen, unless there is a bug in the C + library. + + Use the Py_EncodeLocale() function to encode the character string back to a + byte string. */ +wchar_t* +Py_DecodeLocale(const char* arg, size_t *size) { #if defined(__APPLE__) || defined(__ANDROID__) + return _Py_DecodeUTF8_surrogateescape(arg, strlen(arg), size); +#else + if (Py_UTF8Mode) { + return _Py_DecodeUTF8_surrogateescape(arg, strlen(arg), size); + } + +#ifndef MS_WINDOWS + if (force_ascii == -1) + force_ascii = check_force_ascii(); + + if (force_ascii) { + /* force ASCII encoding to workaround mbstowcs() issue */ + wchar_t *wstr = decode_ascii_surrogateescape(arg, size); + if (wstr == NULL) { + if (size != NULL) { + *size = (size_t)-1; + } + return NULL; + } + return wstr; + } +#endif + + return decode_locale(arg, size); +#endif /* __APPLE__ or __ANDROID__ */ +} + +static char* +_Py_EncodeLocaleUTF8(const wchar_t *text, size_t *error_pos) +{ Py_ssize_t len; PyObject *unicode, *bytes = NULL; char *cpath; unicode = PyUnicode_FromWideChar(text, wcslen(text)); - if (unicode == NULL) + if (unicode == NULL) { return NULL; + } bytes = _PyUnicode_AsUTF8String(unicode, "surrogateescape"); Py_DECREF(unicode); if (bytes == NULL) { PyErr_Clear(); - if (error_pos != NULL) + if (error_pos != NULL) { *error_pos = (size_t)-1; + } return NULL; } @@ -447,27 +443,24 @@ Py_EncodeLocale(const wchar_t *text, size_t *error_pos) if (cpath == NULL) { PyErr_Clear(); Py_DECREF(bytes); - if (error_pos != NULL) + if (error_pos != NULL) { *error_pos = (size_t)-1; + } return NULL; } memcpy(cpath, PyBytes_AsString(bytes), len + 1); Py_DECREF(bytes); return cpath; -#else /* __APPLE__ */ +} + +static char* +encode_locale(const wchar_t *text, size_t *error_pos) +{ const size_t len = wcslen(text); char *result = NULL, *bytes = NULL; size_t i, size, converted; wchar_t c, buf[2]; -#ifndef MS_WINDOWS - if (force_ascii == -1) - force_ascii = check_force_ascii(); - - if (force_ascii) - return encode_ascii_surrogateescape(text, error_pos); -#endif - /* The function works in two steps: 1. compute the length of the output buffer in bytes (size) 2. outputs the bytes */ @@ -522,6 +515,39 @@ Py_EncodeLocale(const wchar_t *text, size_t *error_pos) bytes = result; } return result; +} + +/* Encode a wide character string to the locale encoding with the + surrogateescape error handler: surrogate characters in the range + U+DC80..U+DCFF are converted to bytes 0x80..0xFF. + + Return a pointer to a newly allocated byte string, use PyMem_Free() to free + the memory. Return NULL on encoding or memory allocation error. + + If error_pos is not NULL, *error_pos is set to (size_t)-1 on success, or set + to the index of the invalid character on encoding error. + + Use the Py_DecodeLocale() function to decode the bytes string back to a wide + character string. */ +char* +Py_EncodeLocale(const wchar_t *text, size_t *error_pos) +{ +#if defined(__APPLE__) || defined(__ANDROID__) + return _Py_EncodeLocaleUTF8(text, error_pos); +#else /* __APPLE__ */ + if (Py_UTF8Mode) { + return _Py_EncodeLocaleUTF8(text, error_pos); + } + +#ifndef MS_WINDOWS + if (force_ascii == -1) + force_ascii = check_force_ascii(); + + if (force_ascii) + return encode_ascii_surrogateescape(text, error_pos); +#endif + + return encode_locale(text, error_pos); #endif /* __APPLE__ or __ANDROID__ */ } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index f284855f342..2bac23d1cb0 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -54,7 +54,7 @@ extern grammar _PyParser_Grammar; /* From graminit.c */ static _PyInitError add_main_module(PyInterpreterState *interp); static _PyInitError initfsencoding(PyInterpreterState *interp); static _PyInitError initsite(void); -static _PyInitError init_sys_streams(void); +static _PyInitError init_sys_streams(PyInterpreterState *interp); static _PyInitError initsigs(void); static void call_py_exitfuncs(void); static void wait_for_thread_shutdown(void); @@ -925,7 +925,7 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return err; } - err = init_sys_streams(); + err = init_sys_streams(interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -1410,7 +1410,7 @@ new_interpreter(PyThreadState **tstate_p) return err; } - err = init_sys_streams(); + err = init_sys_streams(interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -1558,7 +1558,13 @@ initfsencoding(PyInterpreterState *interp) Py_FileSystemDefaultEncodeErrors = "surrogatepass"; } #else - if (Py_FileSystemDefaultEncoding == NULL) { + if (Py_FileSystemDefaultEncoding == NULL && + interp->core_config.utf8_mode) + { + Py_FileSystemDefaultEncoding = "utf-8"; + Py_HasFileSystemDefaultEncoding = 1; + } + else if (Py_FileSystemDefaultEncoding == NULL) { Py_FileSystemDefaultEncoding = get_locale_encoding(); if (Py_FileSystemDefaultEncoding == NULL) { return _Py_INIT_ERR("Unable to get the locale encoding"); @@ -1749,7 +1755,7 @@ create_stdio(PyObject* io, /* Initialize sys.stdin, stdout, stderr and builtins.open */ static _PyInitError -init_sys_streams(void) +init_sys_streams(PyInterpreterState *interp) { PyObject *iomod = NULL, *wrapper; PyObject *bimod = NULL; @@ -1794,10 +1800,10 @@ init_sys_streams(void) encoding = _Py_StandardStreamEncoding; errors = _Py_StandardStreamErrors; if (!encoding || !errors) { - pythonioencoding = Py_GETENV("PYTHONIOENCODING"); - if (pythonioencoding) { + char *opt = Py_GETENV("PYTHONIOENCODING"); + if (opt && opt[0] != '\0') { char *err; - pythonioencoding = _PyMem_Strdup(pythonioencoding); + pythonioencoding = _PyMem_Strdup(opt); if (pythonioencoding == NULL) { PyErr_NoMemory(); goto error; @@ -1814,7 +1820,12 @@ init_sys_streams(void) encoding = pythonioencoding; } } - if (!errors && !(pythonioencoding && *pythonioencoding)) { + else if (interp->core_config.utf8_mode) { + encoding = "utf-8"; + errors = "surrogateescape"; + } + + if (!errors && !pythonioencoding) { /* Choose the default error handler based on the current locale */ errors = get_default_standard_stream_error_handler(); } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index f10099b5232..141e189d0b1 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1814,6 +1814,7 @@ static PyStructSequence_Field flags_fields[] = { {"hash_randomization", "-R"}, {"isolated", "-I"}, {"dev_mode", "-X dev"}, + {"utf8_mode", "-X utf8"}, {0} }; @@ -1821,7 +1822,7 @@ static PyStructSequence_Desc flags_desc = { "sys.flags", /* name */ flags__doc__, /* doc */ flags_fields, /* fields */ - 14 + 15 }; static PyObject* @@ -1853,8 +1854,9 @@ make_flags(void) SetFlag(Py_QuietFlag); SetFlag(Py_HashRandomizationFlag); SetFlag(Py_IsolatedFlag); -#undef SetFlag PyStructSequence_SET_ITEM(seq, pos++, PyBool_FromLong(core_config->dev_mode)); + SetFlag(Py_UTF8Mode); +#undef SetFlag if (PyErr_Occurred()) { Py_DECREF(seq); From webhook-mailer at python.org Wed Dec 13 07:37:54 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 13 Dec 2017 12:37:54 -0000 Subject: [Python-checkins] trivial: link updates in documentation (#2765) Message-ID: https://github.com/python/cpython/commit/4f29f3c84b74de8c208980a14bc56bffa6363121 commit: 4f29f3c84b74de8c208980a14bc56bffa6363121 branch: master author: jimmy committer: Andrew Svetlov date: 2017-12-13T14:37:51+02:00 summary: trivial: link updates in documentation (#2765) files: M Doc/faq/extending.rst M Doc/howto/logging-cookbook.rst M Doc/library/mailbox.rst M Doc/library/ssl.rst diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst index 3eafdf193c8..88996e48035 100644 --- a/Doc/faq/extending.rst +++ b/Doc/faq/extending.rst @@ -53,7 +53,7 @@ with a tool such as `SWIG `_. `SIP `__, `CXX `_ `Boost `_, or `Weave -`_ are also +`_ are also alternatives for wrapping C++ libraries. diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 71ee417f2bc..4d2d052d291 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -941,7 +941,7 @@ Using file rotation ------------------- .. sectionauthor:: Doug Hellmann, Vinay Sajip (changes) -.. (see ) +.. (see ) Sometimes you want to let a log file grow to a certain size, then open a new file and log to that. You may want to keep a certain number of these files, and diff --git a/Doc/library/mailbox.rst b/Doc/library/mailbox.rst index 81244c2ed02..48d76a83221 100644 --- a/Doc/library/mailbox.rst +++ b/Doc/library/mailbox.rst @@ -491,7 +491,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. `Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad `_ An argument for using the original mbox format rather than a variation. - `"mbox" is a family of several mutually incompatible mailbox formats `_ + `"mbox" is a family of several mutually incompatible mailbox formats `_ A history of mbox variations. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 6122af18ede..b40d9584104 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1374,7 +1374,7 @@ to speed up repeated connections from the same clients. The *capath* string, if present, is the path to a directory containing several CA certificates in PEM format, following an `OpenSSL specific layout - `_. + `_. The *cadata* object, if present, is either an ASCII string of one or more PEM-encoded certificates or a :term:`bytes-like object` of DER-encoded @@ -1664,7 +1664,7 @@ to speed up repeated connections from the same clients. Get statistics about the SSL sessions created or managed by this context. A dictionary is returned which maps the names of each `piece of information - `_ to their + `_ to their numeric values. For example, here is the total number of hits and misses in the session cache since the context was created:: From webhook-mailer at python.org Wed Dec 13 07:45:16 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 13 Dec 2017 12:45:16 -0000 Subject: [Python-checkins] trivial: link updates in documentation (GH-2765) (#4836) Message-ID: https://github.com/python/cpython/commit/3ff488c082a045467a222aaf77afc66c24192bdd commit: 3ff488c082a045467a222aaf77afc66c24192bdd branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-13T14:45:13+02:00 summary: trivial: link updates in documentation (GH-2765) (#4836) (cherry picked from commit 4f29f3c84b74de8c208980a14bc56bffa6363121) files: M Doc/faq/extending.rst M Doc/howto/logging-cookbook.rst M Doc/library/mailbox.rst M Doc/library/ssl.rst diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst index c3806457b03..4be58d69714 100644 --- a/Doc/faq/extending.rst +++ b/Doc/faq/extending.rst @@ -56,7 +56,7 @@ with a tool such as `SWIG `_. `SIP `__, `CXX `_ `Boost `_, or `Weave -`_ are also +`_ are also alternatives for wrapping C++ libraries. diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index b9b5120f053..50ff76e7928 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -650,7 +650,7 @@ Using file rotation ------------------- .. sectionauthor:: Doug Hellmann, Vinay Sajip (changes) -.. (see ) +.. (see ) Sometimes you want to let a log file grow to a certain size, then open a new file and log to that. You may want to keep a certain number of these files, and diff --git a/Doc/library/mailbox.rst b/Doc/library/mailbox.rst index 9f894cae1df..9c9452f92b1 100644 --- a/Doc/library/mailbox.rst +++ b/Doc/library/mailbox.rst @@ -474,7 +474,7 @@ Maildir, mbox, MH, Babyl, and MMDF. `Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad `_ An argument for using the original mbox format rather than a variation. - `"mbox" is a family of several mutually incompatible mailbox formats `_ + `"mbox" is a family of several mutually incompatible mailbox formats `_ A history of mbox variations. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 93df8d70559..5b55a82f5ec 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1134,7 +1134,7 @@ to speed up repeated connections from the same clients. The *capath* string, if present, is the path to a directory containing several CA certificates in PEM format, following an `OpenSSL specific layout - `_. + `_. The *cadata* object, if present, is either an ASCII string of one or more PEM-encoded certificates or a bytes-like object of DER-encoded @@ -1310,7 +1310,7 @@ to speed up repeated connections from the same clients. Get statistics about the SSL sessions created or managed by this context. A dictionary is returned which maps the names of each `piece of information - `_ to their + `_ to their numeric values. For example, here is the total number of hits and misses in the session cache since the context was created:: From webhook-mailer at python.org Wed Dec 13 07:45:22 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 13 Dec 2017 12:45:22 -0000 Subject: [Python-checkins] trivial: link updates in documentation (GH-2765) (#4835) Message-ID: https://github.com/python/cpython/commit/4a97809a38398930b01874d77927860d84270f16 commit: 4a97809a38398930b01874d77927860d84270f16 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-13T14:45:19+02:00 summary: trivial: link updates in documentation (GH-2765) (#4835) (cherry picked from commit 4f29f3c84b74de8c208980a14bc56bffa6363121) files: M Doc/faq/extending.rst M Doc/howto/logging-cookbook.rst M Doc/library/mailbox.rst M Doc/library/ssl.rst diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst index 3eafdf193c8..88996e48035 100644 --- a/Doc/faq/extending.rst +++ b/Doc/faq/extending.rst @@ -53,7 +53,7 @@ with a tool such as `SWIG `_. `SIP `__, `CXX `_ `Boost `_, or `Weave -`_ are also +`_ are also alternatives for wrapping C++ libraries. diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 44f38e0341c..598df5392f3 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -941,7 +941,7 @@ Using file rotation ------------------- .. sectionauthor:: Doug Hellmann, Vinay Sajip (changes) -.. (see ) +.. (see ) Sometimes you want to let a log file grow to a certain size, then open a new file and log to that. You may want to keep a certain number of these files, and diff --git a/Doc/library/mailbox.rst b/Doc/library/mailbox.rst index 81244c2ed02..48d76a83221 100644 --- a/Doc/library/mailbox.rst +++ b/Doc/library/mailbox.rst @@ -491,7 +491,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. `Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad `_ An argument for using the original mbox format rather than a variation. - `"mbox" is a family of several mutually incompatible mailbox formats `_ + `"mbox" is a family of several mutually incompatible mailbox formats `_ A history of mbox variations. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 495cd590f89..8f219c57940 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1351,7 +1351,7 @@ to speed up repeated connections from the same clients. The *capath* string, if present, is the path to a directory containing several CA certificates in PEM format, following an `OpenSSL specific layout - `_. + `_. The *cadata* object, if present, is either an ASCII string of one or more PEM-encoded certificates or a :term:`bytes-like object` of DER-encoded @@ -1614,7 +1614,7 @@ to speed up repeated connections from the same clients. Get statistics about the SSL sessions created or managed by this context. A dictionary is returned which maps the names of each `piece of information - `_ to their + `_ to their numeric values. For example, here is the total number of hits and misses in the session cache since the context was created:: From webhook-mailer at python.org Wed Dec 13 10:50:20 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 13 Dec 2017 15:50:20 -0000 Subject: [Python-checkins] Fix couple typos (#4839) Message-ID: https://github.com/python/cpython/commit/7a6706bf481070298d603b2e3140be715e9dfdcb commit: 7a6706bf481070298d603b2e3140be715e9dfdcb branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-13T17:50:16+02:00 summary: Fix couple typos (#4839) files: M Lib/asyncio/windows_events.py M Lib/test/test_asyncio/test_proactor_events.py diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index e18fd392ba2..890fce8b405 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -711,7 +711,7 @@ def _poll(self, timeout=None): f.set_result(value) self._results.append(f) - # Remove unregisted futures + # Remove unregistered futures for ov in self._unregistered: self._cache.pop(ov.address, None) self._unregistered.clear() diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 7ccc6814b2e..c3bac95c862 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -423,7 +423,7 @@ def test_pause_writing_3write(self): def test_dont_pause_writing(self): tr = self.pause_writing_transport(high=4) - # write a large chunk which completes immedialty, + # write a large chunk which completes immediately, # it should not pause writing fut = asyncio.Future(loop=self.loop) fut.set_result(None) From webhook-mailer at python.org Wed Dec 13 11:27:43 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 13 Dec 2017 16:27:43 -0000 Subject: [Python-checkins] pythoninfo: Add builtins, test.support, ... (#4840) Message-ID: https://github.com/python/cpython/commit/981469794af8c693174544265b0c19cbe6d2b457 commit: 981469794af8c693174544265b0c19cbe6d2b457 branch: master author: Victor Stinner committer: GitHub date: 2017-12-13T17:27:40+01:00 summary: pythoninfo: Add builtins, test.support, ... (#4840) Collect more info from builtins, resource, test.test_socket and test.support modules. Co-Authored-By: Christian Heimes files: M Lib/test/pythoninfo.py diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 7ad076ddbca..9ca26c99708 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -151,6 +151,11 @@ def collect_locale(info_add): info_add('locale.encoding', locale.getpreferredencoding(False)) +def collect_builtins(info_add): + info_add('builtins.float.float_format', float.__getformat__("float")) + info_add('builtins.float.double_format', float.__getformat__("double")) + + def collect_os(info_add): import os @@ -170,7 +175,7 @@ def format_attr(attr, value): ) copy_attributes(info_add, os, 'os.%s', attributes, formatter=format_attr) - info_add("os.cwd", os.getcwd()) + call_func(info_add, 'os.cwd', os, 'getcwd') call_func(info_add, 'os.uid', os, 'getuid') call_func(info_add, 'os.gid', os, 'getgid') @@ -435,6 +440,44 @@ def collect_testcapi(info_add): copy_attr(info_add, 'pymem.with_pymalloc', _testcapi, 'WITH_PYMALLOC') +def collect_resource(info_add): + try: + import resource + except ImportError: + return + + limits = [attr for attr in dir(resource) if attr.startswith('RLIMIT_')] + for name in limits: + key = getattr(resource, name) + value = resource.getrlimit(key) + info_add('resource.%s' % name, value) + + +def collect_test_socket(info_add): + try: + from test import test_socket + except ImportError: + return + + # all check attributes like HAVE_SOCKET_CAN + attributes = [name for name in dir(test_socket) + if name.startswith('HAVE_')] + copy_attributes(info_add, test_socket, 'test_socket.%s', attributes) + + +def collect_test_support(info_add): + try: + from test import support + except ImportError: + return + + attributes = ('IPV6_ENABLED',) + copy_attributes(info_add, support, 'test_support.%s', attributes) + + call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available') + call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized') + + def collect_info(info): error = False info_add = info.add @@ -443,6 +486,7 @@ def collect_info(info): # collect_os() should be the first, to check the getrandom() status collect_os, + collect_builtins, collect_gdb, collect_locale, collect_platform, @@ -458,6 +502,11 @@ def collect_info(info): collect_expat, collect_decimal, collect_testcapi, + collect_resource, + + # Collecting from tests should be last as they have side effects. + collect_test_socket, + collect_test_support, ): try: collect_func(info_add) From webhook-mailer at python.org Wed Dec 13 11:31:19 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 13 Dec 2017 16:31:19 -0000 Subject: [Python-checkins] pymain_set_sys_argv() now copies argv (#4838) Message-ID: https://github.com/python/cpython/commit/d5dda98fa80405db82e2eb36ac48671b4c8c0983 commit: d5dda98fa80405db82e2eb36ac48671b4c8c0983 branch: master author: Victor Stinner committer: GitHub date: 2017-12-13T17:31:16+01:00 summary: pymain_set_sys_argv() now copies argv (#4838) bpo-29240, bpo-32030: * Rename pymain_set_argv() to pymain_set_sys_argv() * pymain_set_sys_argv() now creates of copy of argv and modify the copy, rather than modifying pymain->argv * Call pymain_set_sys_argv() earlier: before pymain_run_python(), but after pymain_get_importer(). * Add _PySys_SetArgvWithError() to handle errors files: M Include/sysmodule.h M Modules/main.c M Python/sysmodule.c diff --git a/Include/sysmodule.h b/Include/sysmodule.h index 719ecfcf61f..b709629ec6c 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -16,6 +16,12 @@ PyAPI_FUNC(int) _PySys_SetObjectId(_Py_Identifier *key, PyObject *); PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); +#ifdef Py_BUILD_CORE +PyAPI_FUNC(_PyInitError) _PySys_SetArgvWithError( + int argc, + wchar_t **argv, + int updatepath); +#endif PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) diff --git a/Modules/main.c b/Modules/main.c index 9ce111cea99..c8848a607bc 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -434,14 +434,11 @@ typedef struct { /* .cmdline is initialized to zeros */ #define _PyMain_INIT \ - {.status = 0, \ - .cf = {.cf_flags = 0}, \ - .core_config = _PyCoreConfig_INIT, \ + {.core_config = _PyCoreConfig_INIT, \ .config = _PyMainInterpreterConfig_INIT, \ - .main_importer_path = NULL, \ .run_code = -1, \ - .err = _Py_INIT_OK(), \ - .env_warning_options = {0, NULL}} + .err = _Py_INIT_OK()} +/* Note: _PyMain_INIT sets other fields to 0/NULL */ static void @@ -738,6 +735,9 @@ pymain_parse_cmdline_impl(_PyMain *pymain) cmdline->filename = pymain->argv[_PyOS_optind]; } + /* -c and -m options are exclusive */ + assert(!(cmdline->command != NULL && cmdline->module != NULL)); + return 0; } @@ -1082,22 +1082,34 @@ pymain_header(_PyMain *pymain) } -static void -pymain_set_argv(_PyMain *pymain) +static int +pymain_set_sys_argv(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; - /* TODO: Move this to _Py_InitializeMainInterpreter */ - if (cmdline->command != NULL) { - /* Backup _PyOS_optind and force sys.argv[0] = '-c' */ + if (cmdline->command != NULL || cmdline->module != NULL) { + /* Backup _PyOS_optind */ _PyOS_optind--; - pymain->argv[_PyOS_optind] = L"-c"; } - if (cmdline->module != NULL) { - /* Backup _PyOS_optind and force sys.argv[0] = '-m'*/ - _PyOS_optind--; - pymain->argv[_PyOS_optind] = L"-m"; + /* Copy argv to be able to modify it (to force -c/-m) */ + int argc2 = pymain->argc - _PyOS_optind; + size_t size = argc2 * sizeof(pymain->argv[0]); + wchar_t **argv2 = PyMem_RawMalloc(size); + if (argv2 == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } + memcpy(argv2, &pymain->argv[_PyOS_optind], size); + + /* TODO: Move this to _Py_InitializeMainInterpreter */ + if (cmdline->command != NULL) { + /* Force sys.argv[0] = '-c' */ + argv2[0] = L"-c"; + } + else if (cmdline->module != NULL) { + /* Force sys.argv[0] = '-m'*/ + argv2[0] = L"-m"; } int update_path; @@ -1108,9 +1120,18 @@ pymain_set_argv(_PyMain *pymain) /* Use config settings to decide whether or not to update sys.path[0] */ update_path = (Py_IsolatedFlag == 0); } - PySys_SetArgvEx(pymain->argc - _PyOS_optind, - pymain->argv + _PyOS_optind, - update_path); + + /* Set sys.argv. If '-c' and '-m' options are not used in the command line + and update_path is non-zero, prepend argv[0] to sys.path. If argv[0] is + a symlink, use the real path. */ + _PyInitError err = _PySys_SetArgvWithError(argc2, argv2, update_path); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; + return -1; + } + + PyMem_RawFree(argv2); + return 0; } @@ -1604,7 +1625,7 @@ pymain_init_utf8_mode(_PyMain *pymain) } #endif - wchar_t *xopt = pymain_get_xoption(pymain, L"utf8"); + const wchar_t *xopt = pymain_get_xoption(pymain, L"utf8"); if (xopt) { wchar_t *sep = wcschr(xopt, L'='); if (sep) { @@ -1626,7 +1647,7 @@ pymain_init_utf8_mode(_PyMain *pymain) return 0; } - char *opt = pymain_get_env_var("PYTHONUTF8"); + const char *opt = pymain_get_env_var("PYTHONUTF8"); if (opt) { if (strcmp(opt, "1") == 0) { core_config->utf8_mode = 1; @@ -1788,6 +1809,22 @@ pymain_init_python(_PyMain *pymain) if (pymain_init_main_interpreter(pymain)) { return -1; } + + if (pymain->cmdline.filename != NULL) { + /* If filename is a package (ex: directory or ZIP file) which contains + __main__.py, main_importer_path is set to filename and will be + prepended to sys.path by pymain_run_main_from_importer(). Otherwise, + main_importer_path is set to NULL. */ + pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename); + } + + /* FIXME: put argv into _PyMainInterpreterConfig. + Currently, PySys_SetArgvEx() can still modify sys.path and so must be + called after _Py_InitializeMainInterpreter() which calls + _PyPathConfig_Init(). */ + if (pymain_set_sys_argv(pymain) < 0) { + return -1; + } return 0; } @@ -1800,12 +1837,6 @@ pymain_run_python(_PyMain *pymain) pymain_header(pymain); pymain_import_readline(pymain); - if (cmdline->filename != NULL) { - pymain->main_importer_path = pymain_get_importer(cmdline->filename); - } - - pymain_set_argv(pymain); - if (cmdline->command) { pymain->status = pymain_run_command(cmdline->command, &pymain->cf); } @@ -1868,7 +1899,6 @@ pymain_impl(_PyMain *pymain) other special meaning */ pymain->status = 120; } - return 0; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 141e189d0b1..ea2ccb2a152 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2446,17 +2446,34 @@ sys_update_path(int argc, wchar_t **argv) Py_DECREF(a); } -void -PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) +_PyInitError +_PySys_SetArgvWithError(int argc, wchar_t **argv, int updatepath) { PyObject *av = makeargvobject(argc, argv); - if (av == NULL) - Py_FatalError("no mem for sys.argv"); - if (PySys_SetObject("argv", av) != 0) - Py_FatalError("can't assign sys.argv"); + if (av == NULL) { + return _Py_INIT_NO_MEMORY(); + } + if (PySys_SetObject("argv", av) != 0) { + Py_DECREF(av); + return _Py_INIT_ERR("can't assign sys.argv"); + } Py_DECREF(av); - if (updatepath) + + if (updatepath) { + /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path. + If argv[0] is a symlink, use the real path. */ sys_update_path(argc, argv); + } + return _Py_INIT_OK(); +} + +void +PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) +{ + _PyInitError err = _PySys_SetArgvWithError(argc, argv, updatepath); + if (_Py_INIT_FAILED(err)) { + _Py_FatalInitError(err); + } } void From webhook-mailer at python.org Wed Dec 13 14:49:46 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 13 Dec 2017 19:49:46 -0000 Subject: [Python-checkins] bpo-32296: Implement asyncio.get_event_loop and _get_running_loop in C. (#4827) Message-ID: https://github.com/python/cpython/commit/a70232f28882d2fecb3ebe06643867701016070f commit: a70232f28882d2fecb3ebe06643867701016070f branch: master author: Yury Selivanov committer: GitHub date: 2017-12-13T14:49:42-05:00 summary: bpo-32296: Implement asyncio.get_event_loop and _get_running_loop in C. (#4827) asyncio.get_event_loop(), and, subsequently asyncio._get_running_loop() are one of the most frequently executed functions in asyncio. They also can't be sped up by third-party event loops like uvloop. When implemented in C they become 4x faster. files: A Misc/NEWS.d/next/Library/2017-12-12-18-01-01.bpo-32296.bwscHz.rst M Lib/asyncio/events.py M Lib/test/test_asyncio/test_events.py M Modules/_asynciomodule.c M Modules/clinic/_asynciomodule.c.h diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index e425b06e42f..a00f861a9e5 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -652,6 +652,7 @@ def get_running_loop(): This function is thread-specific. """ + # NOTE: this function is implemented in C (see _asynciomodule.c) loop = _get_running_loop() if loop is None: raise RuntimeError('no running event loop') @@ -664,6 +665,7 @@ def _get_running_loop(): This is a low-level function intended to be used by event loops. This function is thread-specific. """ + # NOTE: this function is implemented in C (see _asynciomodule.c) running_loop, pid = _running_loop.loop_pid if running_loop is not None and pid == os.getpid(): return running_loop @@ -675,6 +677,7 @@ def _set_running_loop(loop): This is a low-level function intended to be used by event loops. This function is thread-specific. """ + # NOTE: this function is implemented in C (see _asynciomodule.c) _running_loop.loop_pid = (loop, os.getpid()) @@ -711,6 +714,7 @@ def get_event_loop(): If there is no running event loop set, the function will return the result of `get_event_loop_policy().get_event_loop()` call. """ + # NOTE: this function is implemented in C (see _asynciomodule.c) current_loop = _get_running_loop() if current_loop is not None: return current_loop @@ -736,3 +740,26 @@ def set_child_watcher(watcher): """Equivalent to calling get_event_loop_policy().set_child_watcher(watcher).""" return get_event_loop_policy().set_child_watcher(watcher) + + +# Alias pure-Python implementations for testing purposes. +_py__get_running_loop = _get_running_loop +_py__set_running_loop = _set_running_loop +_py_get_running_loop = get_running_loop +_py_get_event_loop = get_event_loop + + +try: + # get_event_loop() is one of the most frequently called + # functions in asyncio. Pure Python implementation is + # about 4 times slower than C-accelerated. + from _asyncio import (_get_running_loop, _set_running_loop, + get_running_loop, get_event_loop) +except ImportError: + pass +else: + # Alias C implementations for testing purposes. + _c__get_running_loop = _get_running_loop + _c__set_running_loop = _set_running_loop + _c_get_running_loop = get_running_loop + _c_get_event_loop = get_event_loop diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 1315febe403..144921ad0ec 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -27,6 +27,7 @@ import asyncio from asyncio import coroutines +from asyncio import events from asyncio import proactor_events from asyncio import selector_events from test.test_asyncio import utils as test_utils @@ -2145,23 +2146,6 @@ def tearDown(self): asyncio.set_child_watcher(None) super().tearDown() - def test_get_event_loop_new_process(self): - # Issue bpo-32126: The multiprocessing module used by - # ProcessPoolExecutor is not functional when the - # multiprocessing.synchronize module cannot be imported. - support.import_module('multiprocessing.synchronize') - async def main(): - pool = concurrent.futures.ProcessPoolExecutor() - result = await self.loop.run_in_executor( - pool, _test_get_event_loop_new_process__sub_proc) - pool.shutdown() - return result - - self.unpatch_get_running_loop() - - self.assertEqual( - self.loop.run_until_complete(main()), - 'hello') if hasattr(selectors, 'KqueueSelector'): class KqueueEventLoopTests(UnixEventLoopTestsMixin, @@ -2722,17 +2706,95 @@ def test_set_event_loop_policy(self): self.assertIs(policy, asyncio.get_event_loop_policy()) self.assertIsNot(policy, old_policy) + +class GetEventLoopTestsMixin: + + _get_running_loop_impl = None + _set_running_loop_impl = None + get_running_loop_impl = None + get_event_loop_impl = None + + def setUp(self): + self._get_running_loop_saved = events._get_running_loop + self._set_running_loop_saved = events._set_running_loop + self.get_running_loop_saved = events.get_running_loop + self.get_event_loop_saved = events.get_event_loop + + events._get_running_loop = type(self)._get_running_loop_impl + events._set_running_loop = type(self)._set_running_loop_impl + events.get_running_loop = type(self).get_running_loop_impl + events.get_event_loop = type(self).get_event_loop_impl + + asyncio._get_running_loop = type(self)._get_running_loop_impl + asyncio._set_running_loop = type(self)._set_running_loop_impl + asyncio.get_running_loop = type(self).get_running_loop_impl + asyncio.get_event_loop = type(self).get_event_loop_impl + + super().setUp() + + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + watcher = asyncio.SafeChildWatcher() + watcher.attach_loop(self.loop) + asyncio.set_child_watcher(watcher) + + def tearDown(self): + try: + asyncio.set_child_watcher(None) + super().tearDown() + finally: + self.loop.close() + asyncio.set_event_loop(None) + + events._get_running_loop = self._get_running_loop_saved + events._set_running_loop = self._set_running_loop_saved + events.get_running_loop = self.get_running_loop_saved + events.get_event_loop = self.get_event_loop_saved + + asyncio._get_running_loop = self._get_running_loop_saved + asyncio._set_running_loop = self._set_running_loop_saved + asyncio.get_running_loop = self.get_running_loop_saved + asyncio.get_event_loop = self.get_event_loop_saved + + if sys.platform != 'win32': + + def test_get_event_loop_new_process(self): + # Issue bpo-32126: The multiprocessing module used by + # ProcessPoolExecutor is not functional when the + # multiprocessing.synchronize module cannot be imported. + support.import_module('multiprocessing.synchronize') + + async def main(): + pool = concurrent.futures.ProcessPoolExecutor() + result = await self.loop.run_in_executor( + pool, _test_get_event_loop_new_process__sub_proc) + pool.shutdown() + return result + + self.assertEqual( + self.loop.run_until_complete(main()), + 'hello') + def test_get_event_loop_returns_running_loop(self): + class TestError(Exception): + pass + class Policy(asyncio.DefaultEventLoopPolicy): def get_event_loop(self): - raise NotImplementedError - - loop = None + raise TestError old_policy = asyncio.get_event_loop_policy() try: asyncio.set_event_loop_policy(Policy()) loop = asyncio.new_event_loop() + + with self.assertRaises(TestError): + asyncio.get_event_loop() + asyncio.set_event_loop(None) + with self.assertRaises(TestError): + asyncio.get_event_loop() + with self.assertRaisesRegex(RuntimeError, 'no running'): self.assertIs(asyncio.get_running_loop(), None) self.assertIs(asyncio._get_running_loop(), None) @@ -2743,6 +2805,15 @@ def get_event_loop(self): self.assertIs(asyncio._get_running_loop(), loop) loop.run_until_complete(func()) + + asyncio.set_event_loop(loop) + with self.assertRaises(TestError): + asyncio.get_event_loop() + + asyncio.set_event_loop(None) + with self.assertRaises(TestError): + asyncio.get_event_loop() + finally: asyncio.set_event_loop_policy(old_policy) if loop is not None: @@ -2754,5 +2825,27 @@ def get_event_loop(self): self.assertIs(asyncio._get_running_loop(), None) +class TestPyGetEventLoop(GetEventLoopTestsMixin, unittest.TestCase): + + _get_running_loop_impl = events._py__get_running_loop + _set_running_loop_impl = events._py__set_running_loop + get_running_loop_impl = events._py_get_running_loop + get_event_loop_impl = events._py_get_event_loop + + +try: + import _asyncio # NoQA +except ImportError: + pass +else: + + class TestCGetEventLoop(GetEventLoopTestsMixin, unittest.TestCase): + + _get_running_loop_impl = events._c__get_running_loop + _set_running_loop_impl = events._c__set_running_loop + get_running_loop_impl = events._c_get_running_loop + get_event_loop_impl = events._c_get_event_loop + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-12-12-18-01-01.bpo-32296.bwscHz.rst b/Misc/NEWS.d/next/Library/2017-12-12-18-01-01.bpo-32296.bwscHz.rst new file mode 100644 index 00000000000..4100d48518e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-12-18-01-01.bpo-32296.bwscHz.rst @@ -0,0 +1,2 @@ +Implement asyncio._get_running_loop() and get_event_loop() in C. This makes +them 4x faster. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 2c64c55e7e3..01c38b80b95 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -9,9 +9,11 @@ module _asyncio /* identifiers used from some functions */ +_Py_IDENTIFIER(__asyncio_running_event_loop__); _Py_IDENTIFIER(add_done_callback); _Py_IDENTIFIER(call_soon); _Py_IDENTIFIER(cancel); +_Py_IDENTIFIER(get_event_loop); _Py_IDENTIFIER(send); _Py_IDENTIFIER(throw); _Py_IDENTIFIER(_step); @@ -23,7 +25,7 @@ _Py_IDENTIFIER(_wakeup); static PyObject *all_tasks; static PyObject *current_tasks; static PyObject *traceback_extract_stack; -static PyObject *asyncio_get_event_loop; +static PyObject *asyncio_get_event_loop_policy; static PyObject *asyncio_future_repr_info_func; static PyObject *asyncio_task_repr_info_func; static PyObject *asyncio_task_get_stack_func; @@ -31,6 +33,7 @@ static PyObject *asyncio_task_print_stack_func; static PyObject *asyncio_InvalidStateError; static PyObject *asyncio_CancelledError; static PyObject *inspect_isgenerator; +static PyObject *os_getpid; typedef enum { @@ -88,6 +91,134 @@ class _asyncio.Future "FutureObj *" "&Future_Type" static PyObject* future_new_iter(PyObject *); static inline int future_call_schedule_callbacks(FutureObj *); + +static int +get_running_loop(PyObject **loop) +{ + PyObject *ts_dict; + PyObject *running_tuple; + PyObject *running_loop; + PyObject *running_loop_pid; + PyObject *current_pid; + int same_pid; + + ts_dict = PyThreadState_GetDict(); // borrowed + if (ts_dict == NULL) { + PyErr_SetString( + PyExc_RuntimeError, "thread-local storage is not available"); + goto error; + } + + running_tuple = _PyDict_GetItemId( + ts_dict, &PyId___asyncio_running_event_loop__); // borrowed + if (running_tuple == NULL) { + /* _PyDict_GetItemId doesn't set an error if key is not found */ + goto not_found; + } + + assert(PyTuple_CheckExact(running_tuple)); + assert(PyTuple_Size(running_tuple) == 2); + running_loop = PyTuple_GET_ITEM(running_tuple, 0); // borrowed + running_loop_pid = PyTuple_GET_ITEM(running_tuple, 1); // borrowed + + if (running_loop == Py_None) { + goto not_found; + } + + current_pid = _PyObject_CallNoArg(os_getpid); + if (current_pid == NULL) { + goto error; + } + same_pid = PyObject_RichCompareBool(current_pid, running_loop_pid, Py_EQ); + Py_DECREF(current_pid); + if (same_pid == -1) { + goto error; + } + + if (same_pid) { + // current_pid == running_loop_pid + goto found; + } + +not_found: + *loop = NULL; + return 0; + +found: + Py_INCREF(running_loop); + *loop = running_loop; + return 0; + +error: + *loop = NULL; + return -1; +} + + +static int +set_running_loop(PyObject *loop) +{ + PyObject *ts_dict; + PyObject *running_tuple; + PyObject *current_pid; + + ts_dict = PyThreadState_GetDict(); // borrowed + if (ts_dict == NULL) { + PyErr_SetString( + PyExc_RuntimeError, "thread-local storage is not available"); + return -1; + } + + current_pid = _PyObject_CallNoArg(os_getpid); + if (current_pid == NULL) { + return -1; + } + + running_tuple = PyTuple_New(2); + if (running_tuple == NULL) { + Py_DECREF(current_pid); + return -1; + } + + Py_INCREF(loop); + PyTuple_SET_ITEM(running_tuple, 0, loop); + PyTuple_SET_ITEM(running_tuple, 1, current_pid); // borrowed + + if (_PyDict_SetItemId( + ts_dict, &PyId___asyncio_running_event_loop__, running_tuple)) { + Py_DECREF(running_tuple); // will cleanup loop & current_pid + return -1; + } + Py_DECREF(running_tuple); + + return 0; +} + + +static PyObject * +get_event_loop(void) +{ + PyObject *loop; + PyObject *policy; + + if (get_running_loop(&loop)) { + return NULL; + } + if (loop != NULL) { + return loop; + } + + policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy); + if (policy == NULL) { + return NULL; + } + + loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL); + Py_DECREF(policy); + return loop; +} + + static int future_schedule_callbacks(FutureObj *fut) { @@ -140,7 +271,7 @@ future_init(FutureObj *fut, PyObject *loop) _Py_IDENTIFIER(get_debug); if (loop == Py_None) { - loop = _PyObject_CallNoArg(asyncio_get_event_loop); + loop = get_event_loop(); if (loop == NULL) { return -1; } @@ -1449,7 +1580,7 @@ _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop) PyObject *res; if (loop == Py_None) { - loop = _PyObject_CallNoArg(asyncio_get_event_loop); + loop = get_event_loop(); if (loop == NULL) { return NULL; } @@ -1536,7 +1667,7 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) PyObject *res; if (loop == Py_None) { - loop = _PyObject_CallNoArg(asyncio_get_event_loop); + loop = get_event_loop(); if (loop == NULL) { return NULL; } @@ -2368,6 +2499,100 @@ task_wakeup(TaskObj *task, PyObject *o) } +/*********************** Functions **************************/ + + +/*[clinic input] +_asyncio._get_running_loop + +Return the running event loop or None. + +This is a low-level function intended to be used by event loops. +This function is thread-specific. + +[clinic start generated code]*/ + +static PyObject * +_asyncio__get_running_loop_impl(PyObject *module) +/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/ +{ + PyObject *loop; + if (get_running_loop(&loop)) { + return NULL; + } + if (loop == NULL) { + /* There's no currently running event loop */ + Py_RETURN_NONE; + } + return loop; +} + +/*[clinic input] +_asyncio._set_running_loop + loop: 'O' + / + +Set the running event loop. + +This is a low-level function intended to be used by event loops. +This function is thread-specific. +[clinic start generated code]*/ + +static PyObject * +_asyncio__set_running_loop(PyObject *module, PyObject *loop) +/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/ +{ + if (set_running_loop(loop)) { + return NULL; + } + Py_RETURN_NONE; +} + +/*[clinic input] +_asyncio.get_event_loop + +Return an asyncio event loop. + +When called from a coroutine or a callback (e.g. scheduled with +call_soon or similar API), this function will always return the +running event loop. + +If there is no running event loop set, the function will return +the result of `get_event_loop_policy().get_event_loop()` call. +[clinic start generated code]*/ + +static PyObject * +_asyncio_get_event_loop_impl(PyObject *module) +/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/ +{ + return get_event_loop(); +} + +/*[clinic input] +_asyncio.get_running_loop + +Return the running event loop. Raise a RuntimeError if there is none. + +This function is thread-specific. +[clinic start generated code]*/ + +static PyObject * +_asyncio_get_running_loop_impl(PyObject *module) +/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/ +{ + PyObject *loop; + if (get_running_loop(&loop)) { + return NULL; + } + if (loop == NULL) { + /* There's no currently running event loop */ + PyErr_SetString( + PyExc_RuntimeError, "no running event loop"); + } + return loop; +} + + /*********************** Module **************************/ @@ -2377,7 +2602,7 @@ module_free(void *m) Py_CLEAR(current_tasks); Py_CLEAR(all_tasks); Py_CLEAR(traceback_extract_stack); - Py_CLEAR(asyncio_get_event_loop); + Py_CLEAR(asyncio_get_event_loop_policy); Py_CLEAR(asyncio_future_repr_info_func); Py_CLEAR(asyncio_task_repr_info_func); Py_CLEAR(asyncio_task_get_stack_func); @@ -2385,6 +2610,7 @@ module_free(void *m) Py_CLEAR(asyncio_InvalidStateError); Py_CLEAR(asyncio_CancelledError); Py_CLEAR(inspect_isgenerator); + Py_CLEAR(os_getpid); } static int @@ -2407,7 +2633,7 @@ module_init(void) } WITH_MOD("asyncio.events") - GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop") + GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy") WITH_MOD("asyncio.base_futures") GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info") @@ -2422,6 +2648,9 @@ module_init(void) WITH_MOD("inspect") GET_MOD_ATTR(inspect_isgenerator, "isgenerator") + WITH_MOD("os") + GET_MOD_ATTR(os_getpid, "getpid") + WITH_MOD("traceback") GET_MOD_ATTR(traceback_extract_stack, "extract_stack") @@ -2452,12 +2681,20 @@ module_init(void) PyDoc_STRVAR(module_doc, "Accelerator module for asyncio"); +static PyMethodDef asyncio_methods[] = { + _ASYNCIO_GET_EVENT_LOOP_METHODDEF + _ASYNCIO_GET_RUNNING_LOOP_METHODDEF + _ASYNCIO__GET_RUNNING_LOOP_METHODDEF + _ASYNCIO__SET_RUNNING_LOOP_METHODDEF + {NULL, NULL} +}; + static struct PyModuleDef _asynciomodule = { PyModuleDef_HEAD_INIT, /* m_base */ "_asyncio", /* m_name */ module_doc, /* m_doc */ -1, /* m_size */ - NULL, /* m_methods */ + asyncio_methods, /* m_methods */ NULL, /* m_slots */ NULL, /* m_traverse */ NULL, /* m_clear */ diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h index 7627849bb88..8022d1c6f50 100644 --- a/Modules/clinic/_asynciomodule.c.h +++ b/Modules/clinic/_asynciomodule.c.h @@ -517,4 +517,82 @@ _asyncio_Task__wakeup(TaskObj *self, PyObject **args, Py_ssize_t nargs, PyObject exit: return return_value; } -/*[clinic end generated code: output=b92f9cd2b9fb37ef input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_asyncio__get_running_loop__doc__, +"_get_running_loop($module, /)\n" +"--\n" +"\n" +"Return the running event loop or None.\n" +"\n" +"This is a low-level function intended to be used by event loops.\n" +"This function is thread-specific."); + +#define _ASYNCIO__GET_RUNNING_LOOP_METHODDEF \ + {"_get_running_loop", (PyCFunction)_asyncio__get_running_loop, METH_NOARGS, _asyncio__get_running_loop__doc__}, + +static PyObject * +_asyncio__get_running_loop_impl(PyObject *module); + +static PyObject * +_asyncio__get_running_loop(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _asyncio__get_running_loop_impl(module); +} + +PyDoc_STRVAR(_asyncio__set_running_loop__doc__, +"_set_running_loop($module, loop, /)\n" +"--\n" +"\n" +"Set the running event loop.\n" +"\n" +"This is a low-level function intended to be used by event loops.\n" +"This function is thread-specific."); + +#define _ASYNCIO__SET_RUNNING_LOOP_METHODDEF \ + {"_set_running_loop", (PyCFunction)_asyncio__set_running_loop, METH_O, _asyncio__set_running_loop__doc__}, + +PyDoc_STRVAR(_asyncio_get_event_loop__doc__, +"get_event_loop($module, /)\n" +"--\n" +"\n" +"Return an asyncio event loop.\n" +"\n" +"When called from a coroutine or a callback (e.g. scheduled with\n" +"call_soon or similar API), this function will always return the\n" +"running event loop.\n" +"\n" +"If there is no running event loop set, the function will return\n" +"the result of `get_event_loop_policy().get_event_loop()` call."); + +#define _ASYNCIO_GET_EVENT_LOOP_METHODDEF \ + {"get_event_loop", (PyCFunction)_asyncio_get_event_loop, METH_NOARGS, _asyncio_get_event_loop__doc__}, + +static PyObject * +_asyncio_get_event_loop_impl(PyObject *module); + +static PyObject * +_asyncio_get_event_loop(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _asyncio_get_event_loop_impl(module); +} + +PyDoc_STRVAR(_asyncio_get_running_loop__doc__, +"get_running_loop($module, /)\n" +"--\n" +"\n" +"Return the running event loop. Raise a RuntimeError if there is none.\n" +"\n" +"This function is thread-specific."); + +#define _ASYNCIO_GET_RUNNING_LOOP_METHODDEF \ + {"get_running_loop", (PyCFunction)_asyncio_get_running_loop, METH_NOARGS, _asyncio_get_running_loop__doc__}, + +static PyObject * +_asyncio_get_running_loop_impl(PyObject *module); + +static PyObject * +_asyncio_get_running_loop(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _asyncio_get_running_loop_impl(module); +} +/*[clinic end generated code: output=d40b94e629571d48 input=a9049054013a1b77]*/ From webhook-mailer at python.org Wed Dec 13 15:06:00 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 13 Dec 2017 20:06:00 -0000 Subject: [Python-checkins] bpo-32030: Add _PyPathConfig_ComputeArgv0() (#4845) Message-ID: https://github.com/python/cpython/commit/11a247df88f15b51feff8a3c46005676bb29b96e commit: 11a247df88f15b51feff8a3c46005676bb29b96e branch: master author: Victor Stinner committer: GitHub date: 2017-12-13T21:05:57+01:00 summary: bpo-32030: Add _PyPathConfig_ComputeArgv0() (#4845) Changes: * Split _PySys_SetArgvWithError() into subfunctions for Py_Main(): * Create the Python list object * Set sys.argv to the list * Compute argv0 * Prepend argv0 to sys.path * Add _PyPathConfig_ComputeArgv0() * Remove _PySys_SetArgvWithError() * Py_Main() now splits the code to compute sys.argv/path0 and the code to update the sys module: add pymain_compute_argv() subfunction. files: M Include/pylifecycle.h M Include/sysmodule.h M Modules/main.c M Python/pathconfig.c M Python/sysmodule.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 542306004d2..17ed110b83b 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -105,6 +105,7 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( const _PyMainInterpreterConfig *main_config); +PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS diff --git a/Include/sysmodule.h b/Include/sysmodule.h index b709629ec6c..719ecfcf61f 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -16,12 +16,6 @@ PyAPI_FUNC(int) _PySys_SetObjectId(_Py_Identifier *key, PyObject *); PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); -#ifdef Py_BUILD_CORE -PyAPI_FUNC(_PyInitError) _PySys_SetArgvWithError( - int argc, - wchar_t **argv, - int updatepath); -#endif PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) diff --git a/Modules/main.c b/Modules/main.c index c8848a607bc..7c717750610 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -410,6 +410,13 @@ typedef struct { #endif } _Py_CommandLineDetails; +/* FIXME: temporary structure until sys module configuration can be moved + into _PyMainInterpreterConfig */ +typedef struct { + PyObject *argv; /* sys.argv list */ + PyObject *path0; /* path0: if set, it is prepended to sys.path */ +} _PySysConfig; + /* Structure used by Py_Main() to pass data to subfunctions */ typedef struct { /* Exit status ("exit code") */ @@ -419,6 +426,7 @@ typedef struct { int stdin_is_interactive; _PyCoreConfig core_config; _PyMainInterpreterConfig config; + _PySysConfig sys_config; _Py_CommandLineDetails cmdline; PyObject *main_importer_path; /* non-zero if filename, command (-c) or module (-m) is set @@ -492,6 +500,8 @@ pymain_free_pymain(_PyMain *pymain) pymain_optlist_clear(&pymain->env_warning_options); Py_CLEAR(pymain->main_importer_path); + Py_CLEAR(pymain->sys_config.argv); + Py_CLEAR(pymain->sys_config.path0); } static void @@ -510,26 +520,20 @@ pymain_free(_PyMain *pymain) static int pymain_run_main_from_importer(_PyMain *pymain) { - PyObject *sys_path0 = pymain->main_importer_path; - PyObject *sys_path; - int sts; - /* Assume sys_path0 has already been checked by pymain_get_importer(), * so put it in sys.path[0] and import __main__ */ - sys_path = PySys_GetObject("path"); + PyObject *sys_path = PySys_GetObject("path"); if (sys_path == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path"); goto error; } - sts = PyList_Insert(sys_path, 0, sys_path0); - if (sts) { - sys_path0 = NULL; + if (PyList_Insert(sys_path, 0, pymain->main_importer_path)) { goto error; } - sts = pymain_run_module(L"__main__", 0); - return sts != 0; + int sts = pymain_run_module(L"__main__", 0); + return (sts != 0); error: Py_CLEAR(pymain->main_importer_path); @@ -1082,8 +1086,36 @@ pymain_header(_PyMain *pymain) } +static PyObject * +pymain_create_argv_list(int argc, wchar_t **argv) +{ + if (argc <= 0 || argv == NULL) { + /* Ensure at least one (empty) argument is seen */ + static wchar_t *empty_argv[1] = {L""}; + argv = empty_argv; + argc = 1; + } + + PyObject *av = PyList_New(argc); + if (av == NULL) { + return NULL; + } + + for (int i = 0; i < argc; i++) { + PyObject *v = PyUnicode_FromWideChar(argv[i], -1); + if (v == NULL) { + Py_DECREF(av); + return NULL; + } + PyList_SET_ITEM(av, i, v); + } + return av; +} + + +/* Create sys.argv list and maybe also path0 */ static int -pymain_set_sys_argv(_PyMain *pymain) +pymain_compute_argv(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; @@ -1112,6 +1144,14 @@ pymain_set_sys_argv(_PyMain *pymain) argv2[0] = L"-m"; } + /* Create sys.argv list */ + pymain->sys_config.argv = pymain_create_argv_list(argc2, argv2); + if (pymain->sys_config.argv == NULL) { + pymain->err = _Py_INIT_ERR("failed to create sys.argv"); + goto error; + } + + /* Need to update sys.path[0]? */ int update_path; if (pymain->main_importer_path != NULL) { /* Let pymain_run_main_from_importer() adjust sys.path[0] later */ @@ -1121,16 +1161,48 @@ pymain_set_sys_argv(_PyMain *pymain) update_path = (Py_IsolatedFlag == 0); } - /* Set sys.argv. If '-c' and '-m' options are not used in the command line + /* If '-c' and '-m' options are not used in the command line and update_path is non-zero, prepend argv[0] to sys.path. If argv[0] is a symlink, use the real path. */ - _PyInitError err = _PySys_SetArgvWithError(argc2, argv2, update_path); - if (_Py_INIT_FAILED(err)) { - pymain->err = err; + if (update_path) { + pymain->sys_config.path0 = _PyPathConfig_ComputeArgv0(argc2, argv2); + if (pymain->sys_config.path0 == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + goto error; + } + } + PyMem_RawFree(argv2); + return 0; + +error: + return -1; +} + +static int +pymain_set_sys_argv(_PyMain *pymain) +{ + /* Set sys.argv */ + if (PySys_SetObject("argv", pymain->sys_config.argv) != 0) { + pymain->err = _Py_INIT_ERR("can't assign sys.argv"); return -1; } + Py_CLEAR(pymain->sys_config.argv); + + if (pymain->sys_config.path0 != NULL) { + /* Prepend path0 to sys.path */ + PyObject *sys_path = PySys_GetObject("path"); + if (sys_path == NULL) { + pymain->err = _Py_INIT_ERR("can't get sys.path"); + return -1; + } + + if (PyList_Insert(sys_path, 0, pymain->sys_config.path0) < 0) { + pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); + return -1; + } + Py_CLEAR(pymain->sys_config.path0); + } - PyMem_RawFree(argv2); return 0; } @@ -1822,6 +1894,9 @@ pymain_init_python(_PyMain *pymain) Currently, PySys_SetArgvEx() can still modify sys.path and so must be called after _Py_InitializeMainInterpreter() which calls _PyPathConfig_Init(). */ + if (pymain_compute_argv(pymain) < 0) { + return -1; + } if (pymain_set_sys_argv(pymain) < 0) { return -1; } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 53ddfc997da..b17ae822a7a 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -261,6 +261,104 @@ Py_GetProgramName(void) } +#define _HAVE_SCRIPT_ARGUMENT(argc, argv) \ + (argc > 0 && argv0 != NULL && \ + wcscmp(argv0, L"-c") != 0 && wcscmp(argv0, L"-m") != 0) + +/* Compute argv[0] which will be prepended to sys.argv */ +PyObject* +_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv) +{ + wchar_t *argv0; + wchar_t *p = NULL; + Py_ssize_t n = 0; +#ifdef HAVE_READLINK + wchar_t link[MAXPATHLEN+1]; + wchar_t argv0copy[2*MAXPATHLEN+1]; + int nr = 0; +#endif +#if defined(HAVE_REALPATH) + wchar_t fullpath[MAXPATHLEN]; +#elif defined(MS_WINDOWS) + wchar_t fullpath[MAX_PATH]; +#endif + + + argv0 = argv[0]; + +#ifdef HAVE_READLINK + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) + nr = _Py_wreadlink(argv0, link, MAXPATHLEN); + if (nr > 0) { + /* It's a symlink */ + link[nr] = '\0'; + if (link[0] == SEP) + argv0 = link; /* Link to absolute path */ + else if (wcschr(link, SEP) == NULL) + ; /* Link without path */ + else { + /* Must join(dirname(argv0), link) */ + wchar_t *q = wcsrchr(argv0, SEP); + if (q == NULL) + argv0 = link; /* argv0 without path */ + else { + /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */ + wcsncpy(argv0copy, argv0, MAXPATHLEN); + q = wcsrchr(argv0copy, SEP); + wcsncpy(q+1, link, MAXPATHLEN); + q[MAXPATHLEN + 1] = L'\0'; + argv0 = argv0copy; + } + } + } +#endif /* HAVE_READLINK */ + +#if SEP == '\\' + /* Special case for Microsoft filename syntax */ + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { + wchar_t *q; +#if defined(MS_WINDOWS) + /* Replace the first element in argv with the full path. */ + wchar_t *ptemp; + if (GetFullPathNameW(argv0, + Py_ARRAY_LENGTH(fullpath), + fullpath, + &ptemp)) { + argv0 = fullpath; + } +#endif + p = wcsrchr(argv0, SEP); + /* Test for alternate separator */ + q = wcsrchr(p ? p : argv0, '/'); + if (q != NULL) + p = q; + if (p != NULL) { + n = p + 1 - argv0; + if (n > 1 && p[-1] != ':') + n--; /* Drop trailing separator */ + } + } +#else /* All other filename syntaxes */ + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { +#if defined(HAVE_REALPATH) + if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) { + argv0 = fullpath; + } +#endif + p = wcsrchr(argv0, SEP); + } + if (p != NULL) { + n = p + 1 - argv0; +#if SEP == '/' /* Special case for Unix filename syntax */ + if (n > 1) + n--; /* Drop trailing separator */ +#endif /* Unix */ + } +#endif /* All others */ + + return PyUnicode_FromWideChar(argv0, n); +} + #ifdef __cplusplus } #endif diff --git a/Python/sysmodule.c b/Python/sysmodule.c index ea2ccb2a152..b33a316331a 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2336,143 +2336,41 @@ makeargvobject(int argc, wchar_t **argv) av = NULL; break; } - PyList_SetItem(av, i, v); + PyList_SET_ITEM(av, i, v); } } return av; } -#define _HAVE_SCRIPT_ARGUMENT(argc, argv) \ - (argc > 0 && argv0 != NULL && \ - wcscmp(argv0, L"-c") != 0 && wcscmp(argv0, L"-m") != 0) - -static void -sys_update_path(int argc, wchar_t **argv) -{ - wchar_t *argv0; - wchar_t *p = NULL; - Py_ssize_t n = 0; - PyObject *a; - PyObject *path; -#ifdef HAVE_READLINK - wchar_t link[MAXPATHLEN+1]; - wchar_t argv0copy[2*MAXPATHLEN+1]; - int nr = 0; -#endif -#if defined(HAVE_REALPATH) - wchar_t fullpath[MAXPATHLEN]; -#elif defined(MS_WINDOWS) - wchar_t fullpath[MAX_PATH]; -#endif - - path = _PySys_GetObjectId(&PyId_path); - if (path == NULL) - return; - - argv0 = argv[0]; - -#ifdef HAVE_READLINK - if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) - nr = _Py_wreadlink(argv0, link, MAXPATHLEN); - if (nr > 0) { - /* It's a symlink */ - link[nr] = '\0'; - if (link[0] == SEP) - argv0 = link; /* Link to absolute path */ - else if (wcschr(link, SEP) == NULL) - ; /* Link without path */ - else { - /* Must join(dirname(argv0), link) */ - wchar_t *q = wcsrchr(argv0, SEP); - if (q == NULL) - argv0 = link; /* argv0 without path */ - else { - /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */ - wcsncpy(argv0copy, argv0, MAXPATHLEN); - q = wcsrchr(argv0copy, SEP); - wcsncpy(q+1, link, MAXPATHLEN); - q[MAXPATHLEN + 1] = L'\0'; - argv0 = argv0copy; - } - } - } -#endif /* HAVE_READLINK */ -#if SEP == '\\' /* Special case for MS filename syntax */ - if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { - wchar_t *q; -#if defined(MS_WINDOWS) - /* Replace the first element in argv with the full path. */ - wchar_t *ptemp; - if (GetFullPathNameW(argv0, - Py_ARRAY_LENGTH(fullpath), - fullpath, - &ptemp)) { - argv0 = fullpath; - } -#endif - p = wcsrchr(argv0, SEP); - /* Test for alternate separator */ - q = wcsrchr(p ? p : argv0, '/'); - if (q != NULL) - p = q; - if (p != NULL) { - n = p + 1 - argv0; - if (n > 1 && p[-1] != ':') - n--; /* Drop trailing separator */ - } - } -#else /* All other filename syntaxes */ - if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { -#if defined(HAVE_REALPATH) - if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) { - argv0 = fullpath; - } -#endif - p = wcsrchr(argv0, SEP); - } - if (p != NULL) { - n = p + 1 - argv0; -#if SEP == '/' /* Special case for Unix filename syntax */ - if (n > 1) - n--; /* Drop trailing separator */ -#endif /* Unix */ - } -#endif /* All others */ - a = PyUnicode_FromWideChar(argv0, n); - if (a == NULL) - Py_FatalError("no mem for sys.path insertion"); - if (PyList_Insert(path, 0, a) < 0) - Py_FatalError("sys.path.insert(0) failed"); - Py_DECREF(a); -} - -_PyInitError -_PySys_SetArgvWithError(int argc, wchar_t **argv, int updatepath) +void +PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) { PyObject *av = makeargvobject(argc, argv); if (av == NULL) { - return _Py_INIT_NO_MEMORY(); + Py_FatalError("no mem for sys.argv"); } if (PySys_SetObject("argv", av) != 0) { Py_DECREF(av); - return _Py_INIT_ERR("can't assign sys.argv"); + Py_FatalError("can't assign sys.argv"); } Py_DECREF(av); if (updatepath) { /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path. If argv[0] is a symlink, use the real path. */ - sys_update_path(argc, argv); - } - return _Py_INIT_OK(); -} + PyObject *argv0 = _PyPathConfig_ComputeArgv0(argc, argv); + if (argv0 == NULL) { + Py_FatalError("can't compute path0 from argv"); + } -void -PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) -{ - _PyInitError err = _PySys_SetArgvWithError(argc, argv, updatepath); - if (_Py_INIT_FAILED(err)) { - _Py_FatalInitError(err); + PyObject *sys_path = _PySys_GetObjectId(&PyId_path); + if (sys_path != NULL) { + if (PyList_Insert(sys_path, 0, argv0) < 0) { + Py_DECREF(argv0); + Py_FatalError("can't prepend path0 to sys.path"); + } + } + Py_DECREF(argv0); } } From webhook-mailer at python.org Wed Dec 13 17:23:44 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 13 Dec 2017 22:23:44 -0000 Subject: [Python-checkins] pythoninfo: sync with master (#4843) Message-ID: https://github.com/python/cpython/commit/2316c686400841fe1131583820d5b14417a0e089 commit: 2316c686400841fe1131583820d5b14417a0e089 branch: 2.7 author: Victor Stinner committer: GitHub date: 2017-12-13T23:23:40+01:00 summary: pythoninfo: sync with master (#4843) files: M Lib/test/pythoninfo.py M Lib/test/test_socket.py diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 8b029330a2e..4ce06e00eb9 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -1,7 +1,8 @@ """ -Collect various informations about Python to help debugging test failures. +Collect various information about Python to help debugging test failures. """ from __future__ import print_function +import errno import re import sys import traceback @@ -26,8 +27,8 @@ def add(self, key, value): if value is None: return - if not isinstance(value, (int, long)): - if not isinstance(value, basestring): + if not isinstance(value, int): + if not isinstance(value, str): # convert other objects like sys.flags to string value = str(value) @@ -39,7 +40,7 @@ def add(self, key, value): def get_infos(self): """ - Get informations as a key:value dictionary where values are strings. + Get information as a key:value dictionary where values are strings. """ return {key: str(value) for key, value in self.info.items()} @@ -55,6 +56,14 @@ def copy_attributes(info_add, obj, name_fmt, attributes, formatter=None): info_add(name, value) +def copy_attr(info_add, name, mod, attr_name): + try: + value = getattr(mod, attr_name) + except AttributeError: + return + info_add(name, value) + + def call_func(info_add, name, mod, func_name, formatter=None): try: func = getattr(mod, func_name) @@ -68,6 +77,8 @@ def call_func(info_add, name, mod, func_name, formatter=None): def collect_sys(info_add): attributes = ( + '_framework', + 'abiflags', 'api_version', 'builtin_module_names', 'byteorder', @@ -76,20 +87,28 @@ def collect_sys(info_add): 'flags', 'float_info', 'float_repr_style', + 'hash_info', 'hexversion', - 'maxint', + 'implementation', + 'int_info', 'maxsize', 'maxunicode', 'path', 'platform', 'prefix', + 'thread_info', 'version', 'version_info', 'winver', ) copy_attributes(info_add, sys, 'sys.%s', attributes) + call_func(info_add, 'sys.androidapilevel', sys, 'getandroidapilevel') + call_func(info_add, 'sys.windowsversion', sys, 'getwindowsversion') + encoding = sys.getfilesystemencoding() + if hasattr(sys, 'getfilesystemencodeerrors'): + encoding = '%s/%s' % (encoding, sys.getfilesystemencodeerrors()) info_add('sys.filesystem_encoding', encoding) for name in ('stdin', 'stdout', 'stderr'): @@ -129,26 +148,43 @@ def collect_platform(info_add): def collect_locale(info_add): import locale - info_add('locale.encoding', locale.getpreferredencoding(True)) + info_add('locale.encoding', locale.getpreferredencoding(False)) + + +def collect_builtins(info_add): + info_add('builtins.float.float_format', float.__getformat__("float")) + info_add('builtins.float.double_format', float.__getformat__("double")) def collect_os(info_add): import os - attributes = ('name',) - copy_attributes(info_add, os, 'os.%s', attributes) + def format_attr(attr, value): + if attr in ('supports_follow_symlinks', 'supports_fd', + 'supports_effective_ids'): + return str(sorted(func.__name__ for func in value)) + else: + return value - info_add("os.cwd", os.getcwd()) + attributes = ( + 'name', + 'supports_bytes_environ', + 'supports_effective_ids', + 'supports_fd', + 'supports_follow_symlinks', + ) + copy_attributes(info_add, os, 'os.%s', attributes, formatter=format_attr) + + call_func(info_add, 'os.cwd', os, 'getcwd') call_func(info_add, 'os.uid', os, 'getuid') call_func(info_add, 'os.gid', os, 'getgid') call_func(info_add, 'os.uname', os, 'uname') - if hasattr(os, 'getgroups'): - groups = os.getgroups() - groups = map(str, groups) - groups = ', '.join(groups) - info_add("os.groups", groups) + def format_groups(groups): + return ', '.join(map(str, groups)) + + call_func(info_add, 'os.groups', os, 'getgroups', formatter=format_groups) if hasattr(os, 'getlogin'): try: @@ -160,6 +196,7 @@ def collect_os(info_add): else: info_add("os.login", login) + call_func(info_add, 'os.cpu_count', os, 'cpu_count') call_func(info_add, 'os.loadavg', os, 'getloadavg') # Get environment variables: filter to list @@ -190,7 +227,9 @@ def collect_os(info_add): ) for name, value in os.environ.items(): uname = name.upper() - if (uname in ENV_VARS or uname.startswith(("PYTHON", "LC_")) + if (uname in ENV_VARS + # Copy PYTHON* and LC_* variables + or uname.startswith(("PYTHON", "LC_")) # Visual Studio: VS140COMNTOOLS or (uname.startswith("VS") and uname.endswith("COMNTOOLS"))): info_add('os.environ[%s]' % name, value) @@ -200,13 +239,20 @@ def collect_os(info_add): os.umask(mask) info_add("os.umask", '%03o' % mask) - try: - cpu_count = os.sysconf('SC_NPROCESSORS_ONLN') - except (AttributeError, ValueError): - pass - else: - if cpu_count: - info_add('os.sysconf(SC_NPROCESSORS_ONLN)', cpu_count) + if hasattr(os, 'getrandom'): + # PEP 524: Check if system urandom is initialized + try: + try: + os.getrandom(1, os.GRND_NONBLOCK) + state = 'ready (initialized)' + except BlockingIOError as exc: + state = 'not seeded yet (%s)' % exc + info_add('os.getrandom', state) + except OSError as exc: + # Python was compiled on a more recent Linux version + # than the current Linux kernel: ignore OSError(ENOSYS) + if exc.errno != errno.ENOSYS: + raise def collect_readline(info_add): @@ -216,7 +262,7 @@ def collect_readline(info_add): return def format_attr(attr, value): - if isinstance(value, (int, long)): + if isinstance(value, int): return "%#x" % value else: return value @@ -224,6 +270,7 @@ def format_attr(attr, value): attributes = ( "_READLINE_VERSION", "_READLINE_RUNTIME_VERSION", + "_READLINE_LIBRARY_VERSION", ) copy_attributes(info_add, readline, 'readline.%s', attributes, formatter=format_attr) @@ -256,11 +303,11 @@ def collect_tkinter(info_add): copy_attributes(info_add, _tkinter, 'tkinter.%s', attributes) try: - import Tkinter + import tkinter except ImportError: pass else: - tcl = Tkinter.Tcl() + tcl = tkinter.Tcl() patchlevel = tcl.call('info', 'patchlevel') info_add('tkinter.info_patchlevel', patchlevel) @@ -276,6 +323,11 @@ def collect_time(info_add): ) copy_attributes(info_add, time, 'time.%s', attributes) + if hasattr(time, 'get_clock_info'): + for clock in ('time', 'perf_counter'): + tinfo = time.get_clock_info(clock) + info_add('time.%s' % clock, tinfo) + def collect_sysconfig(info_add): import sysconfig @@ -287,7 +339,6 @@ def collect_sysconfig(info_add): 'CCSHARED', 'CFLAGS', 'CFLAGSFORSHARED', - 'PY_LDFLAGS', 'CONFIG_ARGS', 'HOST_GNU_TYPE', 'MACHDEP', @@ -295,6 +346,7 @@ def collect_sysconfig(info_add): 'OPT', 'PY_CFLAGS', 'PY_CFLAGS_NODIST', + 'PY_LDFLAGS', 'Py_DEBUG', 'Py_ENABLE_SHARED', 'SHELL', @@ -368,15 +420,62 @@ def collect_expat(info_add): copy_attributes(info_add, expat, 'expat.%s', attributes) -def collect_multiprocessing(info_add): +def collect_decimal(info_add): + try: + import _decimal + except ImportError: + return + + attributes = ('__libmpdec_version__',) + copy_attributes(info_add, _decimal, '_decimal.%s', attributes) + + +def collect_testcapi(info_add): + try: + import _testcapi + except ImportError: + return + + call_func(info_add, 'pymem.allocator', _testcapi, 'pymem_getallocatorsname') + copy_attr(info_add, 'pymem.with_pymalloc', _testcapi, 'WITH_PYMALLOC') + + +def collect_resource(info_add): + try: + import resource + except ImportError: + return + + limits = [attr for attr in dir(resource) if attr.startswith('RLIMIT_')] + for name in limits: + key = getattr(resource, name) + value = resource.getrlimit(key) + info_add('resource.%s' % name, value) + + +def collect_test_socket(info_add): try: - import multiprocessing + from test import test_socket except ImportError: return - cpu_count = multiprocessing.cpu_count() - if cpu_count: - info_add('multiprocessing.cpu_count', cpu_count) + # all check attributes like HAVE_SOCKET_CAN + attributes = [name for name in dir(test_socket) + if name.startswith('HAVE_')] + copy_attributes(info_add, test_socket, 'test_socket.%s', attributes) + + +def collect_test_support(info_add): + try: + from test import support + except ImportError: + return + + attributes = ('IPV6_ENABLED',) + copy_attributes(info_add, support, 'test_support.%s', attributes) + + call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available') + call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized') def collect_info(info): @@ -384,10 +483,12 @@ def collect_info(info): info_add = info.add for collect_func in ( - collect_expat, + # collect_os() should be the first, to check the getrandom() status + collect_os, + + collect_builtins, collect_gdb, collect_locale, - collect_os, collect_platform, collect_readline, collect_socket, @@ -398,7 +499,14 @@ def collect_info(info): collect_time, collect_tkinter, collect_zlib, - collect_multiprocessing, + collect_expat, + collect_decimal, + collect_testcapi, + collect_resource, + + # Collecting from tests should be last as they have side effects. + collect_test_socket, + collect_test_support, ): try: collect_func(info_add) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 1126fc2b77b..ca53899418c 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -35,7 +35,7 @@ def try_address(host, port=0, family=socket.AF_INET): HOST = test_support.HOST MSG = b'Michael Gilfix was here\n' -SUPPORTS_IPV6 = socket.has_ipv6 and try_address('::1', family=socket.AF_INET6) +SUPPORTS_IPV6 = test_support.IPV6_ENABLED try: import thread From webhook-mailer at python.org Wed Dec 13 17:28:44 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 13 Dec 2017 22:28:44 -0000 Subject: [Python-checkins] bpo-32296: Unbreak tests on Windows (#4850) Message-ID: https://github.com/python/cpython/commit/bfbf04ef18c93ca8cab0453f76aeea1d8fc23fb1 commit: bfbf04ef18c93ca8cab0453f76aeea1d8fc23fb1 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-13T17:28:41-05:00 summary: bpo-32296: Unbreak tests on Windows (#4850) files: M Lib/test/test_asyncio/test_events.py diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 144921ad0ec..45a8bb86f63 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2735,13 +2735,16 @@ def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) - watcher = asyncio.SafeChildWatcher() - watcher.attach_loop(self.loop) - asyncio.set_child_watcher(watcher) + if sys.platform != 'win32': + watcher = asyncio.SafeChildWatcher() + watcher.attach_loop(self.loop) + asyncio.set_child_watcher(watcher) def tearDown(self): try: - asyncio.set_child_watcher(None) + if sys.platform != 'win32': + asyncio.set_child_watcher(None) + super().tearDown() finally: self.loop.close() From webhook-mailer at python.org Wed Dec 13 18:51:53 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 13 Dec 2017 23:51:53 -0000 Subject: [Python-checkins] bpo-32316: Travis CI: use PYTHON_FOR_REGEN=python3 (#4853) Message-ID: https://github.com/python/cpython/commit/1d2a387b9526ef5f4d694734d8022e739f7fd410 commit: 1d2a387b9526ef5f4d694734d8022e739f7fd410 branch: 3.6 author: Victor Stinner committer: GitHub date: 2017-12-14T00:51:45+01:00 summary: bpo-32316: Travis CI: use PYTHON_FOR_REGEN=python3 (#4853) "make regen-all" requires a working python3.6 or python3. Without "python: 3.6", Travis CI provides a "python3.6" script which ony write an error. Use "python3" instead. files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index 031ba792cbb..e624092bba3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,8 @@ matrix: echo "Only docs were updated, stopping build process." exit fi - ./configure + # Build in release mode + ./configure PYTHON_FOR_REGEN=python3 make -s -j4 # Need a venv that can parse covered code. ./python -m venv venv @@ -70,7 +71,8 @@ before_script: echo "Only docs were updated, stopping build process." exit fi - ./configure --with-pydebug + # Build in debug mode + ./configure --with-pydebug PYTHON_FOR_REGEN=python3 make -j4 make -j4 regen-all clinic changes=`git status --porcelain` From webhook-mailer at python.org Wed Dec 13 20:19:20 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Thu, 14 Dec 2017 01:19:20 -0000 Subject: [Python-checkins] bpo-30241: implement contextlib.AbstractAsyncContextManager (#1412) Message-ID: https://github.com/python/cpython/commit/176baa326be4ec2dc70ca0c054b7e2ab7ca6a9cf commit: 176baa326be4ec2dc70ca0c054b7e2ab7ca6a9cf branch: master author: Jelle Zijlstra committer: Yury Selivanov date: 2017-12-13T20:19:17-05:00 summary: bpo-30241: implement contextlib.AbstractAsyncContextManager (#1412) files: A Misc/NEWS.d/next/Library/2017-10-10-18-56-46.bpo-30241.F_go20.rst M Doc/library/contextlib.rst M Doc/whatsnew/3.7.rst M Lib/contextlib.py M Lib/test/test_contextlib_async.py diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index 48ca0da6b95..faa6c8ac23b 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -29,6 +29,17 @@ Functions and classes provided: .. versionadded:: 3.6 +.. class:: AbstractAsyncContextManager + + An :term:`abstract base class` for classes that implement + :meth:`object.__aenter__` and :meth:`object.__aexit__`. A default + implementation for :meth:`object.__aenter__` is provided which returns + ``self`` while :meth:`object.__aexit__` is an abstract method which by default + returns ``None``. See also the definition of + :ref:`async-context-managers`. + + .. versionadded:: 3.7 + .. decorator:: contextmanager diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 81a88a0c82e..80f2a7f3a1e 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -306,8 +306,9 @@ is a list of strings, not bytes. contextlib ---------- -:func:`contextlib.asynccontextmanager` has been added. (Contributed by -Jelle Zijlstra in :issue:`29679`.) +:func:`~contextlib.asynccontextmanager` and +:class:`~contextlib.AbstractAsyncContextManager` have been added. (Contributed +by Jelle Zijlstra in :issue:`29679` and :issue:`30241`.) cProfile -------- diff --git a/Lib/contextlib.py b/Lib/contextlib.py index c1f8a84617f..96c8c22084a 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -6,7 +6,8 @@ from functools import wraps __all__ = ["asynccontextmanager", "contextmanager", "closing", "nullcontext", - "AbstractContextManager", "ContextDecorator", "ExitStack", + "AbstractContextManager", "AbstractAsyncContextManager", + "ContextDecorator", "ExitStack", "redirect_stdout", "redirect_stderr", "suppress"] @@ -30,6 +31,27 @@ def __subclasshook__(cls, C): return NotImplemented +class AbstractAsyncContextManager(abc.ABC): + + """An abstract base class for asynchronous context managers.""" + + async def __aenter__(self): + """Return `self` upon entering the runtime context.""" + return self + + @abc.abstractmethod + async def __aexit__(self, exc_type, exc_value, traceback): + """Raise any exception triggered within the runtime context.""" + return None + + @classmethod + def __subclasshook__(cls, C): + if cls is AbstractAsyncContextManager: + return _collections_abc._check_methods(C, "__aenter__", + "__aexit__") + return NotImplemented + + class ContextDecorator(object): "A base class or mixin that enables context managers to work as decorators." @@ -136,7 +158,8 @@ def __exit__(self, type, value, traceback): raise RuntimeError("generator didn't stop after throw()") -class _AsyncGeneratorContextManager(_GeneratorContextManagerBase): +class _AsyncGeneratorContextManager(_GeneratorContextManagerBase, + AbstractAsyncContextManager): """Helper for @asynccontextmanager.""" async def __aenter__(self): diff --git a/Lib/test/test_contextlib_async.py b/Lib/test/test_contextlib_async.py index 42cc331c0af..447ca965122 100644 --- a/Lib/test/test_contextlib_async.py +++ b/Lib/test/test_contextlib_async.py @@ -1,5 +1,5 @@ import asyncio -from contextlib import asynccontextmanager +from contextlib import asynccontextmanager, AbstractAsyncContextManager import functools from test import support import unittest @@ -20,6 +20,53 @@ def wrapper(*args, **kwargs): return wrapper +class TestAbstractAsyncContextManager(unittest.TestCase): + + @_async_test + async def test_enter(self): + class DefaultEnter(AbstractAsyncContextManager): + async def __aexit__(self, *args): + await super().__aexit__(*args) + + manager = DefaultEnter() + self.assertIs(await manager.__aenter__(), manager) + + async with manager as context: + self.assertIs(manager, context) + + def test_exit_is_abstract(self): + class MissingAexit(AbstractAsyncContextManager): + pass + + with self.assertRaises(TypeError): + MissingAexit() + + def test_structural_subclassing(self): + class ManagerFromScratch: + async def __aenter__(self): + return self + async def __aexit__(self, exc_type, exc_value, traceback): + return None + + self.assertTrue(issubclass(ManagerFromScratch, AbstractAsyncContextManager)) + + class DefaultEnter(AbstractAsyncContextManager): + async def __aexit__(self, *args): + await super().__aexit__(*args) + + self.assertTrue(issubclass(DefaultEnter, AbstractAsyncContextManager)) + + class NoneAenter(ManagerFromScratch): + __aenter__ = None + + self.assertFalse(issubclass(NoneAenter, AbstractAsyncContextManager)) + + class NoneAexit(ManagerFromScratch): + __aexit__ = None + + self.assertFalse(issubclass(NoneAexit, AbstractAsyncContextManager)) + + class AsyncContextManagerTestCase(unittest.TestCase): @_async_test diff --git a/Misc/NEWS.d/next/Library/2017-10-10-18-56-46.bpo-30241.F_go20.rst b/Misc/NEWS.d/next/Library/2017-10-10-18-56-46.bpo-30241.F_go20.rst new file mode 100644 index 00000000000..9b6c6f6e422 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-10-18-56-46.bpo-30241.F_go20.rst @@ -0,0 +1 @@ +Add contextlib.AbstractAsyncContextManager. Patch by Jelle Zijlstra. From webhook-mailer at python.org Wed Dec 13 20:20:55 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 14 Dec 2017 01:20:55 -0000 Subject: [Python-checkins] bpo-32030: Rewrite _PyMainInterpreterConfig (#4854) Message-ID: https://github.com/python/cpython/commit/b5fd9ad05e0f15f8272b8f1b829af22077230584 commit: b5fd9ad05e0f15f8272b8f1b829af22077230584 branch: master author: Victor Stinner committer: GitHub date: 2017-12-14T02:20:52+01:00 summary: bpo-32030: Rewrite _PyMainInterpreterConfig (#4854) _PyMainInterpreterConfig now contains Python objects, whereas _PyCoreConfig contains wchar_t* strings. Core config: * Rename _PyMainInterpreterConfig_ReadEnv() to _PyCoreConfig_ReadEnv() * Move 3 strings from _PyMainInterpreterConfig to _PyCoreConfig: module_search_path_env, home, program_name. * Add _PyCoreConfig_Clear() * _PyPathConfig_Calculate() now takes core config rather than main config * _PyMainInterpreterConfig_Read() now requires also a core config Main config: * Add _PyMainInterpreterConfig.module_search_path: sys.path list * Add _PyMainInterpreterConfig.argv: sys.argv list * _PyMainInterpreterConfig_Read() now computes module_search_path files: M Include/internal/pystate.h M Include/pylifecycle.h M Include/pystate.h M Modules/getpath.c M Modules/main.c M PC/getpathp.c M Python/pathconfig.c M Python/pylifecycle.c diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 6b527fbe214..305526d136c 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -61,7 +61,7 @@ PyAPI_DATA(_PyPathConfig) _Py_path_config; PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate( _PyPathConfig *config, - const _PyMainInterpreterConfig *main_config); + const _PyCoreConfig *core_config); PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 17ed110b83b..61ed6ccf021 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -54,8 +54,11 @@ PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, PyAPI_FUNC(_PyInitError) _Py_InitializeCore(const _PyCoreConfig *); PyAPI_FUNC(int) _Py_IsCoreInitialized(void); -PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *); -PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_ReadEnv(_PyCoreConfig *); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *); +PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); + +PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *, _PyCoreConfig *); PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *); PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *); @@ -103,8 +106,7 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE -PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( - const _PyMainInterpreterConfig *main_config); +PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(const _PyCoreConfig *core_config); PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); diff --git a/Include/pystate.h b/Include/pystate.h index c7ea179cf7d..9a26cc3909f 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -39,6 +39,11 @@ typedef struct { int dump_refs; /* PYTHONDUMPREFS */ int malloc_stats; /* PYTHONMALLOCSTATS */ int utf8_mode; /* -X utf8 or PYTHONUTF8 environment variable */ + + wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ + wchar_t *home; /* PYTHONHOME environment variable, + see also Py_SetPythonHome(). */ + wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ } _PyCoreConfig; #define _PyCoreConfig_INIT (_PyCoreConfig){.use_hash_seed = -1} @@ -52,12 +57,8 @@ typedef struct { */ typedef struct { int install_signal_handlers; - /* PYTHONPATH environment variable */ - wchar_t *module_search_path_env; - /* PYTHONHOME environment variable, see also Py_SetPythonHome(). */ - wchar_t *home; - /* Program name, see also Py_GetProgramName() */ - wchar_t *program_name; + PyObject *argv; /* sys.argv list, can be NULL */ + PyObject *module_search_path; /* sys.path list */ } _PyMainInterpreterConfig; #define _PyMainInterpreterConfig_INIT \ diff --git a/Modules/getpath.c b/Modules/getpath.c index 11babf0a00b..6208a17f02e 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -356,15 +356,15 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) bytes long. */ static int -search_for_prefix(const _PyMainInterpreterConfig *main_config, +search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *prefix) { size_t n; wchar_t *vpath; /* If PYTHONHOME is set, we believe it unconditionally */ - if (main_config->home) { - wcsncpy(prefix, main_config->home, MAXPATHLEN); + if (core_config->home) { + wcsncpy(prefix, core_config->home, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; wchar_t *delim = wcschr(prefix, DELIM); if (delim) { @@ -423,10 +423,10 @@ search_for_prefix(const _PyMainInterpreterConfig *main_config, static void -calculate_prefix(const _PyMainInterpreterConfig *main_config, +calculate_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *prefix) { - calculate->prefix_found = search_for_prefix(main_config, calculate, prefix); + calculate->prefix_found = search_for_prefix(core_config, calculate, prefix); if (!calculate->prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -468,19 +468,19 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) MAXPATHLEN bytes long. */ static int -search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, +search_for_exec_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *exec_prefix) { size_t n; /* If PYTHONHOME is set, we believe it unconditionally */ - if (main_config->home) { - wchar_t *delim = wcschr(main_config->home, DELIM); + if (core_config->home) { + wchar_t *delim = wcschr(core_config->home, DELIM); if (delim) { wcsncpy(exec_prefix, delim+1, MAXPATHLEN); } else { - wcsncpy(exec_prefix, main_config->home, MAXPATHLEN); + wcsncpy(exec_prefix, core_config->home, MAXPATHLEN); } exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, calculate->lib_python); @@ -551,10 +551,10 @@ search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, static void -calculate_exec_prefix(const _PyMainInterpreterConfig *main_config, +calculate_exec_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *exec_prefix) { - calculate->exec_prefix_found = search_for_exec_prefix(main_config, + calculate->exec_prefix_found = search_for_exec_prefix(core_config, calculate, exec_prefix); if (!calculate->exec_prefix_found) { @@ -587,7 +587,7 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static _PyInitError -calculate_program_full_path(const _PyMainInterpreterConfig *main_config, +calculate_program_full_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; @@ -607,8 +607,8 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, * other way to find a directory to start the search from. If * $PATH isn't exported, you lose. */ - if (wcschr(main_config->program_name, SEP)) { - wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); + if (wcschr(core_config->program_name, SEP)) { + wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -650,7 +650,7 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_full_path, main_config->program_name); + joinpath(program_full_path, core_config->program_name); if (isxfile(program_full_path)) { break; } @@ -815,15 +815,15 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) static _PyInitError -calculate_module_search_path(const _PyMainInterpreterConfig *main_config, +calculate_module_search_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, _PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; - if (main_config->module_search_path_env != NULL) { - bufsz += wcslen(main_config->module_search_path_env) + 1; + if (core_config->module_search_path_env != NULL) { + bufsz += wcslen(core_config->module_search_path_env) + 1; } wchar_t *defpath = calculate->pythonpath; @@ -857,8 +857,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, buf[0] = '\0'; /* Run-time value of $PYTHONPATH goes first */ - if (main_config->module_search_path_env) { - wcscpy(buf, main_config->module_search_path_env); + if (core_config->module_search_path_env) { + wcscpy(buf, core_config->module_search_path_env); wcscat(buf, delimiter); } @@ -907,7 +907,7 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, static _PyInitError calculate_init(PyCalculatePath *calculate, - const _PyMainInterpreterConfig *main_config) + const _PyCoreConfig *core_config) { size_t len; const char *path = getenv("PATH"); @@ -950,12 +950,12 @@ calculate_free(PyCalculatePath *calculate) static _PyInitError -calculate_path_impl(const _PyMainInterpreterConfig *main_config, +calculate_path_impl(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { _PyInitError err; - err = calculate_program_full_path(main_config, calculate, config); + err = calculate_program_full_path(core_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -969,13 +969,13 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); - calculate_prefix(main_config, calculate, prefix); + calculate_prefix(core_config, calculate, prefix); calculate_zip_path(calculate, prefix); wchar_t exec_prefix[MAXPATHLEN+1]; memset(exec_prefix, 0, sizeof(exec_prefix)); - calculate_exec_prefix(main_config, calculate, exec_prefix); + calculate_exec_prefix(core_config, calculate, exec_prefix); if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !Py_FrozenFlag) @@ -984,7 +984,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, "Consider setting $PYTHONHOME to [:]\n"); } - err = calculate_module_search_path(main_config, calculate, + err = calculate_module_search_path(core_config, calculate, prefix, exec_prefix, config); if (_Py_INIT_FAILED(err)) { return err; @@ -1009,18 +1009,17 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, _PyInitError -_PyPathConfig_Calculate(_PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config) { PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - _PyInitError err = calculate_init(&calculate, main_config); + _PyInitError err = calculate_init(&calculate, core_config); if (_Py_INIT_FAILED(err)) { goto done; } - err = calculate_path_impl(main_config, &calculate, config); + err = calculate_path_impl(core_config, &calculate, config); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Modules/main.c b/Modules/main.c index 7c717750610..3f942fe067a 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -410,13 +410,6 @@ typedef struct { #endif } _Py_CommandLineDetails; -/* FIXME: temporary structure until sys module configuration can be moved - into _PyMainInterpreterConfig */ -typedef struct { - PyObject *argv; /* sys.argv list */ - PyObject *path0; /* path0: if set, it is prepended to sys.path */ -} _PySysConfig; - /* Structure used by Py_Main() to pass data to subfunctions */ typedef struct { /* Exit status ("exit code") */ @@ -426,7 +419,6 @@ typedef struct { int stdin_is_interactive; _PyCoreConfig core_config; _PyMainInterpreterConfig config; - _PySysConfig sys_config; _Py_CommandLineDetails cmdline; PyObject *main_importer_path; /* non-zero if filename, command (-c) or module (-m) is set @@ -438,6 +430,9 @@ typedef struct { _Py_OptList env_warning_options; int argc; wchar_t **argv; + + int sys_argc; + wchar_t **sys_argv; } _PyMain; /* .cmdline is initialized to zeros */ @@ -472,7 +467,7 @@ pymain_free_globals(_PyMain *pymain) { _PyPathConfig_Clear(&_Py_path_config); _PyImport_Fini2(); - _PyMainInterpreterConfig_Clear(&pymain->config); + _PyCoreConfig_Clear(&pymain->core_config); #ifdef __INSURE__ /* Insure++ is a memory analysis tool that aids in discovering @@ -497,13 +492,21 @@ pymain_free_pymain(_PyMain *pymain) pymain_optlist_clear(&cmdline->xoptions); PyMem_RawFree(cmdline->command); + PyMem_RawFree(pymain->sys_argv); pymain_optlist_clear(&pymain->env_warning_options); +} + + +/* Clear Python ojects */ +static void +pymain_free_python(_PyMain *pymain) +{ Py_CLEAR(pymain->main_importer_path); - Py_CLEAR(pymain->sys_config.argv); - Py_CLEAR(pymain->sys_config.path0); + _PyMainInterpreterConfig_Clear(&pymain->config); } + static void pymain_free(_PyMain *pymain) { @@ -511,12 +514,14 @@ pymain_free(_PyMain *pymain) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + pymain_free_python(pymain); pymain_free_pymain(pymain); pymain_free_globals(pymain); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } + static int pymain_run_main_from_importer(_PyMain *pymain) { @@ -974,7 +979,7 @@ pymain_init_stdio(_PyMain *pymain) /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ environment variables on macOS if available. */ static _PyInitError -config_get_program_name(_PyMainInterpreterConfig *config) +config_get_program_name(_PyCoreConfig *config) { assert(config->program_name == NULL); @@ -1035,10 +1040,10 @@ config_get_program_name(_PyMainInterpreterConfig *config) static int pymain_get_program_name(_PyMain *pymain) { - if (pymain->config.program_name == NULL) { + if (pymain->core_config.program_name == NULL) { /* Use argv[0] by default */ - pymain->config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); - if (pymain->config.program_name == NULL) { + pymain->core_config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); + if (pymain->core_config.program_name == NULL) { return -1; } } @@ -1086,36 +1091,40 @@ pymain_header(_PyMain *pymain) } -static PyObject * -pymain_create_argv_list(int argc, wchar_t **argv) +static int +pymain_create_argv_list(_PyMain *pymain) { - if (argc <= 0 || argv == NULL) { + int argc = pymain->sys_argc; + wchar_t** argv = pymain->sys_argv; + + if (argc <= 0 || pymain->sys_argv == NULL) { /* Ensure at least one (empty) argument is seen */ static wchar_t *empty_argv[1] = {L""}; argv = empty_argv; argc = 1; } - PyObject *av = PyList_New(argc); - if (av == NULL) { - return NULL; + PyObject *list = PyList_New(argc); + if (list == NULL) { + return -1; } for (int i = 0; i < argc; i++) { PyObject *v = PyUnicode_FromWideChar(argv[i], -1); if (v == NULL) { - Py_DECREF(av); - return NULL; + Py_DECREF(list); + return -1; } - PyList_SET_ITEM(av, i, v); + PyList_SET_ITEM(list, i, v); } - return av; + + pymain->config.argv = list; + return 0; } -/* Create sys.argv list and maybe also path0 */ static int -pymain_compute_argv(_PyMain *pymain) +pymain_init_sys_argv(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; @@ -1125,83 +1134,60 @@ pymain_compute_argv(_PyMain *pymain) } /* Copy argv to be able to modify it (to force -c/-m) */ - int argc2 = pymain->argc - _PyOS_optind; - size_t size = argc2 * sizeof(pymain->argv[0]); - wchar_t **argv2 = PyMem_RawMalloc(size); - if (argv2 == NULL) { + pymain->sys_argc = pymain->argc - _PyOS_optind; + size_t size = pymain->sys_argc * sizeof(pymain->argv[0]); + pymain->sys_argv = PyMem_RawMalloc(size); + if (pymain->sys_argv == NULL) { pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - memcpy(argv2, &pymain->argv[_PyOS_optind], size); + memcpy(pymain->sys_argv, &pymain->argv[_PyOS_optind], size); - /* TODO: Move this to _Py_InitializeMainInterpreter */ if (cmdline->command != NULL) { /* Force sys.argv[0] = '-c' */ - argv2[0] = L"-c"; + pymain->sys_argv[0] = L"-c"; } else if (cmdline->module != NULL) { /* Force sys.argv[0] = '-m'*/ - argv2[0] = L"-m"; + pymain->sys_argv[0] = L"-m"; } + return 0; +} - /* Create sys.argv list */ - pymain->sys_config.argv = pymain_create_argv_list(argc2, argv2); - if (pymain->sys_config.argv == NULL) { - pymain->err = _Py_INIT_ERR("failed to create sys.argv"); - goto error; - } - /* Need to update sys.path[0]? */ - int update_path; +static int +pymain_update_sys_path(_PyMain *pymain) +{ if (pymain->main_importer_path != NULL) { /* Let pymain_run_main_from_importer() adjust sys.path[0] later */ - update_path = 0; - } else { - /* Use config settings to decide whether or not to update sys.path[0] */ - update_path = (Py_IsolatedFlag == 0); - } - - /* If '-c' and '-m' options are not used in the command line - and update_path is non-zero, prepend argv[0] to sys.path. If argv[0] is - a symlink, use the real path. */ - if (update_path) { - pymain->sys_config.path0 = _PyPathConfig_ComputeArgv0(argc2, argv2); - if (pymain->sys_config.path0 == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); - goto error; - } + return 0; } - PyMem_RawFree(argv2); - return 0; -error: - return -1; -} + if (Py_IsolatedFlag) { + return 0; + } -static int -pymain_set_sys_argv(_PyMain *pymain) -{ - /* Set sys.argv */ - if (PySys_SetObject("argv", pymain->sys_config.argv) != 0) { - pymain->err = _Py_INIT_ERR("can't assign sys.argv"); + /* Prepend argv[0] to sys.path. + If argv[0] is a symlink, use the real path. */ + PyObject *sys_path = PySys_GetObject("path"); + if (sys_path == NULL) { + pymain->err = _Py_INIT_ERR("can't get sys.path"); return -1; } - Py_CLEAR(pymain->sys_config.argv); - if (pymain->sys_config.path0 != NULL) { - /* Prepend path0 to sys.path */ - PyObject *sys_path = PySys_GetObject("path"); - if (sys_path == NULL) { - pymain->err = _Py_INIT_ERR("can't get sys.path"); - return -1; - } + PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->sys_argc, pymain->sys_argv); + if (path0 == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } - if (PyList_Insert(sys_path, 0, pymain->sys_config.path0) < 0) { - pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); - return -1; - } - Py_CLEAR(pymain->sys_config.path0); + /* Prepend path0 to sys.path */ + if (PyList_Insert(sys_path, 0, path0) < 0) { + Py_DECREF(path0); + pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); + return -1; } + Py_DECREF(path0); return 0; } @@ -1627,7 +1613,7 @@ config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name) static _PyInitError -config_init_pythonpath(_PyMainInterpreterConfig *config) +config_init_pythonpath(_PyCoreConfig *config) { wchar_t *path; int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH"); @@ -1640,7 +1626,7 @@ config_init_pythonpath(_PyMainInterpreterConfig *config) static _PyInitError -config_init_home(_PyMainInterpreterConfig *config) +config_init_home(_PyCoreConfig *config) { wchar_t *home; @@ -1664,7 +1650,7 @@ config_init_home(_PyMainInterpreterConfig *config) _PyInitError -_PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) +_PyCoreConfig_ReadEnv(_PyCoreConfig *config) { _PyInitError err = config_init_home(config); if (_Py_INIT_FAILED(err)) { @@ -1756,7 +1742,7 @@ pymain_parse_envvars(_PyMain *pymain) return -1; } - _PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config); + _PyInitError err = _PyCoreConfig_ReadEnv(&pymain->core_config); if (_Py_INIT_FAILED(pymain->err)) { pymain->err = err; return -1; @@ -1834,12 +1820,15 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) } /* FIXME: if utf8_mode value changed, parse again cmdline */ - _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config); + if (pymain_init_sys_argv(pymain) < 0) { + return -1; + } + + _PyInitError err = _PyCoreConfig_Read(&pymain->core_config); if (_Py_INIT_FAILED(err)) { pymain->err = err; return -1; } - return 0; } @@ -1858,10 +1847,85 @@ pymain_parse_cmdline_envvars(_PyMain *pymain) return res; } -static int -pymain_init_python(_PyMain *pymain) + +static PyObject * +config_create_path_list(const wchar_t *path, wchar_t delim) { + int i, n; + const wchar_t *p; + PyObject *v; + + n = 1; + p = path; + while ((p = wcschr(p, delim)) != NULL) { + n++; + p++; + } + v = PyList_New(n); + if (v == NULL) { + return NULL; + } + for (i = 0; ; i++) { + p = wcschr(path, delim); + if (p == NULL) { + p = path + wcslen(path); /* End of string */ + } + PyObject *w = PyUnicode_FromWideChar(path, (Py_ssize_t)(p - path)); + if (w == NULL) { + Py_DECREF(v); + return NULL; + } + PyList_SET_ITEM(v, i, w); + if (*p == '\0') { + break; + } + path = p+1; + } + return v; +} + + +static _PyInitError +config_init_module_search_path(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) +{ + _PyInitError err = _PyPathConfig_Init(core_config); + if (_Py_INIT_FAILED(err)) { + return err; + } + wchar_t *sys_path = Py_GetPath(); + + config->module_search_path = config_create_path_list(sys_path, DELIM); + if (config->module_search_path == NULL) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); +} + + +_PyInitError +_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) +{ + /* Signal handlers are installed by default */ + if (config->install_signal_handlers < 0) { + config->install_signal_handlers = 1; + } + + if (config->module_search_path == NULL && + !core_config->_disable_importlib) + { + _PyInitError err = config_init_module_search_path(config, core_config); + if (_Py_INIT_FAILED(err)) { + return err; + } + } + return _Py_INIT_OK(); +} + + +static int +pymain_init_python_core(_PyMain *pymain) +{ pymain_set_global_config(pymain); pymain_init_stdio(pymain); @@ -1870,7 +1934,13 @@ pymain_init_python(_PyMain *pymain) if (_Py_INIT_FAILED(pymain->err)) { return -1; } + return 0; +} + +static int +pymain_init_python_main(_PyMain *pymain) +{ if (pymain_add_xoptions(pymain)) { return -1; } @@ -1878,6 +1948,19 @@ pymain_init_python(_PyMain *pymain) return -1; } + /* Create sys.argv list */ + if (pymain_create_argv_list(pymain) < 0) { + pymain->err = _Py_INIT_ERR("failed to create sys.argv"); + return -1; + } + + _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config, + &pymain->core_config); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; + return -1; + } + if (pymain_init_main_interpreter(pymain)) { return -1; } @@ -1890,14 +1973,7 @@ pymain_init_python(_PyMain *pymain) pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename); } - /* FIXME: put argv into _PyMainInterpreterConfig. - Currently, PySys_SetArgvEx() can still modify sys.path and so must be - called after _Py_InitializeMainInterpreter() which calls - _PyPathConfig_Init(). */ - if (pymain_compute_argv(pymain) < 0) { - return -1; - } - if (pymain_set_sys_argv(pymain) < 0) { + if (pymain_update_sys_path(pymain) < 0) { return -1; } return 0; @@ -1962,13 +2038,20 @@ pymain_impl(_PyMain *pymain) return 0; } - res = pymain_init_python(pymain); + res = pymain_init_python_core(pymain); + if (res < 0) { + return -1; + } + + res = pymain_init_python_main(pymain); if (res < 0) { return -1; } pymain_run_python(pymain); + pymain_free_python(pymain); + if (Py_FinalizeEx() < 0) { /* Value unlikely to be confused with a non-error exit status or other special meaning */ diff --git a/PC/getpathp.c b/PC/getpathp.c index e142e365052..fe4ef1a1ab3 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -498,7 +498,7 @@ get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) static _PyInitError -get_program_full_path(const _PyMainInterpreterConfig *main_config, +get_program_full_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; @@ -514,13 +514,13 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, * $PATH isn't exported, you lose. */ #ifdef ALTSEP - if (wcschr(main_config->program_name, SEP) || - wcschr(main_config->program_name, ALTSEP)) + if (wcschr(core_config->program_name, SEP) || + wcschr(core_config->program_name, ALTSEP)) #else - if (wcschr(main_config->program_name, SEP)) + if (wcschr(core_config->program_name, SEP)) #endif { - wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); + wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN); } else if (calculate->path_env) { const wchar_t *path = calculate->path_env; @@ -539,7 +539,7 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, main_config->program_name); + join(program_full_path, core_config->program_name); if (exists(program_full_path)) { break; } @@ -707,9 +707,9 @@ read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path, static void calculate_init(PyCalculatePath *calculate, - const _PyMainInterpreterConfig *main_config) + const _PyCoreConfig *core_config) { - calculate->home = main_config->home; + calculate->home = core_config->home; calculate->path_env = _wgetenv(L"PATH"); } @@ -813,7 +813,7 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) static _PyInitError -calculate_module_search_path(const _PyMainInterpreterConfig *main_config, +calculate_module_search_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) { @@ -824,7 +824,7 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (main_config->module_search_path_env != NULL || + int skipdefault = (core_config->module_search_path_env != NULL || calculate->home != NULL || calculate->machine_path != NULL || calculate->user_path != NULL); @@ -863,8 +863,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, bufsz += wcslen(calculate->machine_path) + 1; } bufsz += wcslen(calculate->zip_path) + 1; - if (main_config->module_search_path_env != NULL) { - bufsz += wcslen(main_config->module_search_path_env) + 1; + if (core_config->module_search_path_env != NULL) { + bufsz += wcslen(core_config->module_search_path_env) + 1; } wchar_t *buf, *start_buf; @@ -872,9 +872,9 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, if (buf == NULL) { /* We can't exit, so print a warning and limp along */ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); - if (main_config->module_search_path_env) { + if (core_config->module_search_path_env) { fprintf(stderr, "Using environment $PYTHONPATH.\n"); - config->module_search_path = main_config->module_search_path_env; + config->module_search_path = core_config->module_search_path_env; } else { fprintf(stderr, "Using default static path.\n"); @@ -884,9 +884,9 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, } start_buf = buf; - if (main_config->module_search_path_env) { + if (core_config->module_search_path_env) { if (wcscpy_s(buf, bufsz - (buf - start_buf), - main_config->module_search_path_env)) { + core_config->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -999,7 +999,7 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, static _PyInitError -calculate_path_impl(const _PyMainInterpreterConfig *main_config, +calculate_path_impl(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { _PyInitError err; @@ -1009,7 +1009,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, return err; } - err = get_program_full_path(main_config, calculate, config); + err = get_program_full_path(core_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1035,7 +1035,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, calculate_home_prefix(calculate, prefix); - err = calculate_module_search_path(main_config, calculate, config, prefix); + err = calculate_module_search_path(core_config, calculate, config, prefix); if (_Py_INIT_FAILED(err)) { return err; } @@ -1059,15 +1059,14 @@ calculate_free(PyCalculatePath *calculate) _PyInitError -_PyPathConfig_Calculate(_PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config) { PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - calculate_init(&calculate, main_config); + calculate_init(&calculate, core_config); - _PyInitError err = calculate_path_impl(main_config, &calculate, config); + _PyInitError err = calculate_path_impl(core_config, &calculate, config); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index b17ae822a7a..748084ba448 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -46,7 +46,7 @@ _PyPathConfig_Clear(_PyPathConfig *config) /* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Init(const _PyCoreConfig *core_config) { if (_Py_path_config.module_search_path) { /* Already initialized */ @@ -61,15 +61,15 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) /* Calculate program_full_path, prefix, exec_prefix (Unix) or dll_path (Windows), and module_search_path */ - err = _PyPathConfig_Calculate(&new_config, main_config); + err = _PyPathConfig_Calculate(&new_config, core_config); if (_Py_INIT_FAILED(err)) { _PyPathConfig_Clear(&new_config); goto done; } - /* Copy home and program_name from main_config */ - if (main_config->home != NULL) { - new_config.home = _PyMem_RawWcsdup(main_config->home); + /* Copy home and program_name from core_config */ + if (core_config->home != NULL) { + new_config.home = _PyMem_RawWcsdup(core_config->home); if (new_config.home == NULL) { err = _Py_INIT_NO_MEMORY(); goto done; @@ -79,7 +79,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) new_config.home = NULL; } - new_config.program_name = _PyMem_RawWcsdup(main_config->program_name); + new_config.program_name = _PyMem_RawWcsdup(core_config->program_name); if (new_config.program_name == NULL) { err = _Py_INIT_NO_MEMORY(); goto done; @@ -105,14 +105,14 @@ pathconfig_global_init(void) } _PyInitError err; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + _PyCoreConfig config = _PyCoreConfig_INIT; - err = _PyMainInterpreterConfig_ReadEnv(&config); + err = _PyCoreConfig_ReadEnv(&config); if (_Py_INIT_FAILED(err)) { goto error; } - err = _PyMainInterpreterConfig_Read(&config); + err = _PyCoreConfig_Read(&config); if (_Py_INIT_FAILED(err)) { goto error; } @@ -122,11 +122,11 @@ pathconfig_global_init(void) goto error; } - _PyMainInterpreterConfig_Clear(&config); + _PyCoreConfig_Clear(&config); return; error: - _PyMainInterpreterConfig_Clear(&config); + _PyCoreConfig_Clear(&config); _Py_FatalInitError(err); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2bac23d1cb0..31965f503ca 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -792,13 +792,8 @@ _Py_InitializeCore(const _PyCoreConfig *config) */ _PyInitError -_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) +_PyCoreConfig_Read(_PyCoreConfig *config) { - /* Signal handlers are installed by default */ - if (config->install_signal_handlers < 0) { - config->install_signal_handlers = 1; - } - if (config->program_name == NULL) { #ifdef MS_WINDOWS const wchar_t *program_name = L"python"; @@ -814,9 +809,8 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) return _Py_INIT_OK(); } - void -_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) +_PyCoreConfig_Clear(_PyCoreConfig *config) { #define CLEAR(ATTR) \ do { \ @@ -831,6 +825,14 @@ _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) } +void +_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) +{ + Py_CLEAR(config->argv); + Py_CLEAR(config->module_search_path); +} + + /* Update interpreter state based on supplied configuration settings * * After calling this function, most of the restrictions on the interpreter @@ -881,16 +883,11 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return _Py_INIT_ERR("can't initialize time"); } - /* GetPath may initialize state that _PySys_EndInit locks - in, and so has to be called first. */ - err = _PyPathConfig_Init(&interp->config); - if (_Py_INIT_FAILED(err)) { - return err; + assert(interp->config.module_search_path != NULL); + if (PySys_SetObject("path", interp->config.module_search_path) != 0) { + return _Py_INIT_ERR("can't assign sys.path"); } - wchar_t *sys_path = Py_GetPath(); - /* Finish setting up the sys module and import system */ - PySys_SetPath(sys_path); if (_PySys_EndInit(interp->sysdict) < 0) return _Py_INIT_ERR("can't finish initializing sys"); @@ -949,6 +946,12 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) } } + if (interp->config.argv != NULL) { + if (PySys_SetObject("argv", interp->config.argv) != 0) { + return _Py_INIT_ERR("can't assign sys.argv"); + } + } + return _Py_INIT_OK(); } @@ -970,12 +973,12 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) goto done; } - err = _PyMainInterpreterConfig_ReadEnv(&config); + err = _PyCoreConfig_ReadEnv(&core_config); if (_Py_INIT_FAILED(err)) { goto done; } - err = _PyMainInterpreterConfig_Read(&config); + err = _PyMainInterpreterConfig_Read(&config, &core_config); if (_Py_INIT_FAILED(err)) { goto done; } @@ -988,6 +991,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) err = _Py_INIT_OK(); done: + _PyCoreConfig_Clear(&core_config); _PyMainInterpreterConfig_Clear(&config); return err; } @@ -1342,7 +1346,7 @@ new_interpreter(PyThreadState **tstate_p) interp->config = main_interp->config; } - err = _PyPathConfig_Init(&interp->config); + err = _PyPathConfig_Init(&interp->core_config); if (_Py_INIT_FAILED(err)) { return err; } From lp_benchmark_robot at intel.com Wed Dec 13 22:03:17 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 13 Dec 2017 19:03:17 -0800 Subject: [Python-checkins] [2 down, 1 up, 62 flat] Results for Python (master branch) 2017-12-13 Message-ID: Results for project python/master, build date: 2017-12-13 03:03:23-08:00. - commit: c3e070f - previous commit: 5ce0a2a - revision date: 2017-12-13 10:39:55+02:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.734% | +0.831% | +4.931% | +8.590% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 2.981% | +2.170% | +24.649% | +9.398% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.410% | +2.774% | +25.307% | +9.283% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 2.369% | +1.319% | +22.746% | +9.003% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.995% | -0.819% | +6.544% | +15.214% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.720% | +1.280% | +10.428% | +13.981% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.032% | -1.247% | +6.127% | +12.646% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.490% | +0.490% | +0.156% | +9.467% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.292% | -1.032% | +6.649% | +20.842% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.201% | +2.073% | +12.715% | +14.805% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.652% | +1.477% | +3.444% | +9.239% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.388% | +1.287% | +4.781% | +6.030% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.608% | +0.884% | +2.728% | +8.266% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.006% | +1.649% | +13.885% | +9.313% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.413% | +0.197% | +8.359% | +12.006% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.814% | +1.044% | +5.586% | +13.203% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.638% | +1.678% | +11.032% | +11.782% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.693% | +1.821% | +8.963% | +8.758% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.031% | -0.150% | +2.531% | +11.537% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 2.696% | -3.711% | -2.797% | +14.489% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.407% | +0.583% | +5.982% | +13.177% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.066% | +2.058% | +47.533% | +12.739% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.416% | +1.631% | +7.430% | +13.762% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.684% | +2.016% | +17.853% | +13.808% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 3.155% | +3.044% | +8.601% | +10.254% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.285% | -1.445% | +2.141% | +7.671% | +-----+------------------------+--------+------------+------------+------------+ | :-) | nbody| 1.424% | +3.354% | +2.036% | -1.737% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 3.797% | -1.894% | +3.684% | +9.202% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.314% | +0.070% | +7.421% | +7.374% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 3.585% | -0.402% | +0.882% | +19.654% | +-----+------------------------+--------+------------+------------+------------+ | :-( | pickle_dict| 0.289% | -2.311% | -0.691% | +23.216% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.747% | +1.725% | +4.065% | +19.904% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.437% | +1.659% | +10.645% | +11.239% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.144% | +0.217% | +0.227% | +10.301% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.138% | -0.087% | +10.157% | +5.619% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.111% | -0.227% | +1.234% | +5.606% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.834% | -0.419% | +9.413% | +13.859% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 6.216% | -1.918% | +2.404% | +12.316% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.742% | -0.029% | -0.797% | +11.072% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.811% | +0.363% | -3.618% | +5.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.847% | +0.898% | +4.962% | +9.870% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.279% | +1.147% | +8.713% | +15.305% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 1.948% | -1.474% | -3.696% | +5.698% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.629% | -1.638% | +26.229% | +11.322% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.930% | +3.144% | +5.684% | +5.654% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.783% | +0.872% | +13.717% | +11.139% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 4.948% | +1.089% | -2.198% | +3.943% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.549% | -1.017% | +3.971% | +5.876% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.377% | +0.368% | +6.885% | +6.198% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.041% | -0.416% | +6.421% | +3.088% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.827% | -3.353% | +16.759% | +9.994% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.261% | +0.148% | +11.219% | +8.423% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.487% | +0.176% | +9.153% | +7.220% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.038% | -0.048% | +10.558% | +9.060% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 4.971% | -1.800% | +8.349% | +12.393% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.683% | +0.245% | +19.604% | +14.119% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.186% | -0.635% | +4.973% | +8.245% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.641% | +0.430% | +2.802% | +2.357% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.031% | +3.889% | +6.177% | +19.996% | +-----+------------------------+--------+------------+------------+------------+ | :-( | unpickle_list| 1.228% | -3.970% | -3.722% | +17.659% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 5.298% | +1.975% | +4.599% | +10.842% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.652% | +0.343% | +5.980% | +8.136% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.378% | -1.375% | +2.540% | +10.869% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.656% | -2.209% | -9.325% | +14.214% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.395% | -0.009% | +7.114% | +9.256% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/2-down-1-up-62-flat-results-for-python-master-branch-2017-12-13 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu Dec 14 02:47:24 2017 From: webhook-mailer at python.org (INADA Naoki) Date: Thu, 14 Dec 2017 07:47:24 -0000 Subject: [Python-checkins] bpo-29469: Move constant folding to AST optimizer (GH-2858) Message-ID: https://github.com/python/cpython/commit/7ea143ae795a9fd57eaccf490d316bdc13ee9065 commit: 7ea143ae795a9fd57eaccf490d316bdc13ee9065 branch: master author: INADA Naoki committer: GitHub date: 2017-12-14T16:47:20+09:00 summary: bpo-29469: Move constant folding to AST optimizer (GH-2858) files: A Misc/NEWS.d/next/Core and Builtins/2017-07-26-00-20-15.bpo-29469.potmyI.rst A Python/ast_opt.c M Doc/whatsnew/3.7.rst M Include/compile.h M Makefile.pre.in M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/compile.c M Python/importlib.h M Python/importlib_external.h M Python/peephole.c diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 80f2a7f3a1e..d6d0861d5d5 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -581,6 +581,9 @@ Optimizations and :meth:`selectors.DevpollSelector.modify` may be around 10% faster under heavy loads. (Contributed by Giampaolo Rodola' in :issue:`30014`) +* Constant folding is moved from peephole optimizer to new AST optimizer. + (Contributed by Eugene Toder and INADA Naoki in :issue:`29469`) + Build and C API Changes ======================= diff --git a/Include/compile.h b/Include/compile.h index 3cc351d4098..2e9accf5edb 100644 --- a/Include/compile.h +++ b/Include/compile.h @@ -75,6 +75,8 @@ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); #define PY_INVALID_STACK_EFFECT INT_MAX PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg); +PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena); + #ifdef __cplusplus } #endif diff --git a/Makefile.pre.in b/Makefile.pre.in index 14f6f8abc54..fcce62f2577 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -319,6 +319,7 @@ PYTHON_OBJS= \ Python/Python-ast.o \ Python/asdl.o \ Python/ast.o \ + Python/ast_opt.o \ Python/bltinmodule.o \ Python/ceval.o \ Python/compile.o \ diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-07-26-00-20-15.bpo-29469.potmyI.rst b/Misc/NEWS.d/next/Core and Builtins/2017-07-26-00-20-15.bpo-29469.potmyI.rst new file mode 100644 index 00000000000..138a913a4f8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-07-26-00-20-15.bpo-29469.potmyI.rst @@ -0,0 +1,2 @@ +Move constant folding from bytecode layer to AST layer. +Original patch by Eugene Toder. diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index b430e05b629..1dca3ccca1d 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -356,6 +356,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index c9aa3da355e..969ba0850b2 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -824,6 +824,9 @@ Python + + Python + Python diff --git a/Python/ast_opt.c b/Python/ast_opt.c new file mode 100644 index 00000000000..80531cc6ac5 --- /dev/null +++ b/Python/ast_opt.c @@ -0,0 +1,649 @@ +/* AST Optimizer */ +#include "Python.h" +#include "Python-ast.h" + + +/* TODO: is_const and get_const_value are copied from Python/compile.c. + It should be deduped in the future. Maybe, we can include this file + from compile.c? +*/ +static int +is_const(expr_ty e) +{ + switch (e->kind) { + case Constant_kind: + case Num_kind: + case Str_kind: + case Bytes_kind: + case Ellipsis_kind: + case NameConstant_kind: + return 1; + default: + return 0; + } +} + +static PyObject * +get_const_value(expr_ty e) +{ + switch (e->kind) { + case Constant_kind: + return e->v.Constant.value; + case Num_kind: + return e->v.Num.n; + case Str_kind: + return e->v.Str.s; + case Bytes_kind: + return e->v.Bytes.s; + case Ellipsis_kind: + return Py_Ellipsis; + case NameConstant_kind: + return e->v.NameConstant.value; + default: + Py_UNREACHABLE(); + } +} + +static int +make_const(expr_ty node, PyObject *val, PyArena *arena) +{ + if (val == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { + return 0; + } + PyErr_Clear(); + return 1; + } + if (PyArena_AddPyObject(arena, val) < 0) { + Py_DECREF(val); + return 0; + } + node->kind = Constant_kind; + node->v.Constant.value = val; + return 1; +} + +#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr))) + +static PyObject* +unary_not(PyObject *v) +{ + int r = PyObject_IsTrue(v); + if (r < 0) + return NULL; + return PyBool_FromLong(!r); +} + +static int +fold_unaryop(expr_ty node, PyArena *arena) +{ + expr_ty arg = node->v.UnaryOp.operand; + + if (!is_const(arg)) { + /* Fold not into comparison */ + if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind && + asdl_seq_LEN(arg->v.Compare.ops) == 1) { + /* Eq and NotEq are often implemented in terms of one another, so + folding not (self == other) into self != other breaks implementation + of !=. Detecting such cases doesn't seem worthwhile. + Python uses for 'is subset'/'is superset' operations on sets. + They don't satisfy not folding laws. */ + int op = asdl_seq_GET(arg->v.Compare.ops, 0); + switch (op) { + case Is: + op = IsNot; + break; + case IsNot: + op = Is; + break; + case In: + op = NotIn; + break; + case NotIn: + op = In; + break; + default: + op = 0; + } + if (op) { + asdl_seq_SET(arg->v.Compare.ops, 0, op); + COPY_NODE(node, arg); + return 1; + } + } + return 1; + } + + typedef PyObject *(*unary_op)(PyObject*); + static const unary_op ops[] = { + [Invert] = PyNumber_Invert, + [Not] = unary_not, + [UAdd] = PyNumber_Positive, + [USub] = PyNumber_Negative, + }; + PyObject *newval = ops[node->v.UnaryOp.op](get_const_value(arg)); + return make_const(node, newval, arena); +} + +static int +fold_binop(expr_ty node, PyArena *arena) +{ + expr_ty lhs, rhs; + lhs = node->v.BinOp.left; + rhs = node->v.BinOp.right; + if (!is_const(lhs) || !is_const(rhs)) { + return 1; + } + + PyObject *lv = get_const_value(lhs); + PyObject *rv = get_const_value(rhs); + PyObject *newval; + + switch (node->v.BinOp.op) { + case Add: + newval = PyNumber_Add(lv, rv); + break; + case Sub: + newval = PyNumber_Subtract(lv, rv); + break; + case Mult: + newval = PyNumber_Multiply(lv, rv); + break; + case Div: + newval = PyNumber_TrueDivide(lv, rv); + break; + case FloorDiv: + newval = PyNumber_FloorDivide(lv, rv); + break; + case Mod: + newval = PyNumber_Remainder(lv, rv); + break; + case Pow: + newval = PyNumber_Power(lv, rv, Py_None); + break; + case LShift: + newval = PyNumber_Lshift(lv, rv); + break; + case RShift: + newval = PyNumber_Rshift(lv, rv); + break; + case BitOr: + newval = PyNumber_Or(lv, rv); + break; + case BitXor: + newval = PyNumber_Xor(lv, rv); + break; + case BitAnd: + newval = PyNumber_And(lv, rv); + break; + default: // Unknown operator + return 1; + } + + if (newval == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { + return 0; + } + PyErr_Clear(); + return 1; + } + + /* Avoid creating large constants. */ + Py_ssize_t size = PyObject_Size(newval); + if (size == -1) { + if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { + Py_DECREF(newval); + return 0; + } + PyErr_Clear(); + } + else if (size > 20) { + Py_DECREF(newval); + return 1; + } + return make_const(node, newval, arena); +} + +static PyObject* +make_const_tuple(asdl_seq *elts, int make_set) +{ + for (int i = 0; i < asdl_seq_LEN(elts); i++) { + expr_ty e = (expr_ty)asdl_seq_GET(elts, i); + if (!is_const(e)) { + return NULL; + } + } + + PyObject *newval = PyTuple_New(asdl_seq_LEN(elts)); + if (newval == NULL) { + return NULL; + } + + for (int i = 0; i < asdl_seq_LEN(elts); i++) { + expr_ty e = (expr_ty)asdl_seq_GET(elts, i); + PyObject *v = get_const_value(e); + Py_INCREF(v); + PyTuple_SET_ITEM(newval, i, v); + } + + /* Need to create frozen_set instead. */ + if (make_set) { + Py_SETREF(newval, PyFrozenSet_New(newval)); + } + return newval; +} + +static int +fold_tuple(expr_ty node, PyArena *arena) +{ + PyObject *newval; + + if (node->v.Tuple.ctx != Load) + return 1; + + newval = make_const_tuple(node->v.Tuple.elts, 0); + return make_const(node, newval, arena); +} + +static int +fold_subscr(expr_ty node, PyArena *arena) +{ + PyObject *newval; + expr_ty arg, idx; + slice_ty slice; + + arg = node->v.Subscript.value; + slice = node->v.Subscript.slice; + if (node->v.Subscript.ctx != Load || + !is_const(arg) || + /* TODO: handle other types of slices */ + slice->kind != Index_kind || + !is_const(slice->v.Index.value)) + { + return 1; + } + + idx = slice->v.Index.value; + newval = PyObject_GetItem(get_const_value(arg), get_const_value(idx)); + return make_const(node, newval, arena); +} + +static int +fold_compare(expr_ty node, PyArena *arena) +{ + asdl_int_seq *ops; + asdl_seq *args; + PyObject *newval; + int i; + + ops = node->v.Compare.ops; + args = node->v.Compare.comparators; + /* TODO: optimize cases with literal arguments. */ + for (i = 0; i < asdl_seq_LEN(ops); i++) { + int op; + expr_ty arg; + asdl_seq *elts; + + op = asdl_seq_GET(ops, i); + arg = (expr_ty)asdl_seq_GET(args, i); + /* Change literal list or set in 'in' or 'not in' into + tuple or frozenset respectively. */ + /* TODO: do the same when list or set is used as iterable + in for loop and comprehensions? */ + if (op != In && op != NotIn) + continue; + if (arg->kind == List_kind) + elts = arg->v.List.elts; + else if (arg->kind == Set_kind) + elts = arg->v.Set.elts; + else continue; + + newval = make_const_tuple(elts, arg->kind == Set_kind); + make_const(arg, newval, arena); + } + return 1; +} + +static int astfold_mod(mod_ty node_, PyArena* ctx_); +static int astfold_stmt(stmt_ty node_, PyArena* ctx_); +static int astfold_expr(expr_ty node_, PyArena* ctx_); +static int astfold_arguments(arguments_ty node_, PyArena* ctx_); +static int astfold_comprehension(comprehension_ty node_, PyArena* ctx_); +static int astfold_keyword(keyword_ty node_, PyArena* ctx_); +static int astfold_slice(slice_ty node_, PyArena* ctx_); +static int astfold_arg(arg_ty node_, PyArena* ctx_); +static int astfold_withitem(withitem_ty node_, PyArena* ctx_); +static int astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_); +#define CALL(FUNC, TYPE, ARG) \ + if (!FUNC((ARG), ctx_)) \ + return 0; + +#define CALL_OPT(FUNC, TYPE, ARG) \ + if ((ARG) != NULL && !FUNC((ARG), ctx_)) \ + return 0; + +#define CALL_SEQ(FUNC, TYPE, ARG) { \ + int i; \ + asdl_seq *seq = (ARG); /* avoid variable capture */ \ + for (i = 0; i < asdl_seq_LEN(seq); i++) { \ + TYPE elt = (TYPE)asdl_seq_GET(seq, i); \ + if (elt != NULL && !FUNC(elt, ctx_)) \ + return 0; \ + } \ +} + +#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \ + int i; \ + asdl_int_seq *seq = (ARG); /* avoid variable capture */ \ + for (i = 0; i < asdl_seq_LEN(seq); i++) { \ + TYPE elt = (TYPE)asdl_seq_GET(seq, i); \ + if (!FUNC(elt, ctx_)) \ + return 0; \ + } \ +} + +static int +astfold_mod(mod_ty node_, PyArena* ctx_) +{ + switch (node_->kind) { + case Module_kind: + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Module.body); + break; + case Interactive_kind: + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body); + break; + case Expression_kind: + CALL(astfold_expr, expr_ty, node_->v.Expression.body); + break; + case Suite_kind: + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body); + break; + default: + break; + } + return 1; +} + +static int +astfold_expr(expr_ty node_, PyArena* ctx_) +{ + switch (node_->kind) { + case BoolOp_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values); + break; + case BinOp_kind: + CALL(astfold_expr, expr_ty, node_->v.BinOp.left); + CALL(astfold_expr, expr_ty, node_->v.BinOp.right); + CALL(fold_binop, expr_ty, node_); + break; + case UnaryOp_kind: + CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand); + CALL(fold_unaryop, expr_ty, node_); + break; + case Lambda_kind: + CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args); + CALL(astfold_expr, expr_ty, node_->v.Lambda.body); + break; + case IfExp_kind: + CALL(astfold_expr, expr_ty, node_->v.IfExp.test); + CALL(astfold_expr, expr_ty, node_->v.IfExp.body); + CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse); + break; + case Dict_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys); + CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values); + break; + case Set_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts); + break; + case ListComp_kind: + CALL(astfold_expr, expr_ty, node_->v.ListComp.elt); + CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators); + break; + case SetComp_kind: + CALL(astfold_expr, expr_ty, node_->v.SetComp.elt); + CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators); + break; + case DictComp_kind: + CALL(astfold_expr, expr_ty, node_->v.DictComp.key); + CALL(astfold_expr, expr_ty, node_->v.DictComp.value); + CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators); + break; + case GeneratorExp_kind: + CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt); + CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators); + break; + case Await_kind: + CALL(astfold_expr, expr_ty, node_->v.Await.value); + break; + case Yield_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value); + break; + case YieldFrom_kind: + CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value); + break; + case Compare_kind: + CALL(astfold_expr, expr_ty, node_->v.Compare.left); + CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators); + CALL(fold_compare, expr_ty, node_); + break; + case Call_kind: + CALL(astfold_expr, expr_ty, node_->v.Call.func); + CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args); + CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords); + break; + case FormattedValue_kind: + CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value); + CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec); + break; + case JoinedStr_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values); + break; + case Attribute_kind: + CALL(astfold_expr, expr_ty, node_->v.Attribute.value); + break; + case Subscript_kind: + CALL(astfold_expr, expr_ty, node_->v.Subscript.value); + CALL(astfold_slice, slice_ty, node_->v.Subscript.slice); + CALL(fold_subscr, expr_ty, node_); + break; + case Starred_kind: + CALL(astfold_expr, expr_ty, node_->v.Starred.value); + break; + case List_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts); + break; + case Tuple_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts); + CALL(fold_tuple, expr_ty, node_); + break; + default: + break; + } + return 1; +} + +static int +astfold_slice(slice_ty node_, PyArena* ctx_) +{ + switch (node_->kind) { + case Slice_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower); + CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper); + CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step); + break; + case ExtSlice_kind: + CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims); + break; + case Index_kind: + CALL(astfold_expr, expr_ty, node_->v.Index.value); + break; + default: + break; + } + return 1; +} + +static int +astfold_keyword(keyword_ty node_, PyArena* ctx_) +{ + CALL(astfold_expr, expr_ty, node_->value); + return 1; +} + +static int +astfold_comprehension(comprehension_ty node_, PyArena* ctx_) +{ + CALL(astfold_expr, expr_ty, node_->target); + CALL(astfold_expr, expr_ty, node_->iter); + CALL_SEQ(astfold_expr, expr_ty, node_->ifs); + return 1; +} + +static int +astfold_arguments(arguments_ty node_, PyArena* ctx_) +{ + CALL_SEQ(astfold_arg, arg_ty, node_->args); + CALL_OPT(astfold_arg, arg_ty, node_->vararg); + CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs); + CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults); + CALL_OPT(astfold_arg, arg_ty, node_->kwarg); + CALL_SEQ(astfold_expr, expr_ty, node_->defaults); + return 1; +} + +static int +astfold_arg(arg_ty node_, PyArena* ctx_) +{ + CALL_OPT(astfold_expr, expr_ty, node_->annotation); + return 1; +} + +static int +astfold_stmt(stmt_ty node_, PyArena* ctx_) +{ + switch (node_->kind) { + case FunctionDef_kind: + CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.FunctionDef.body); + CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list); + CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns); + break; + case AsyncFunctionDef_kind: + CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFunctionDef.body); + CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list); + CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns); + break; + case ClassDef_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases); + CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ClassDef.body); + CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list); + break; + case Return_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value); + break; + case Delete_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets); + break; + case Assign_kind: + CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets); + CALL(astfold_expr, expr_ty, node_->v.Assign.value); + break; + case AugAssign_kind: + CALL(astfold_expr, expr_ty, node_->v.AugAssign.target); + CALL(astfold_expr, expr_ty, node_->v.AugAssign.value); + break; + case AnnAssign_kind: + CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target); + CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation); + CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value); + break; + case For_kind: + CALL(astfold_expr, expr_ty, node_->v.For.target); + CALL(astfold_expr, expr_ty, node_->v.For.iter); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse); + break; + case AsyncFor_kind: + CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target); + CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse); + break; + case While_kind: + CALL(astfold_expr, expr_ty, node_->v.While.test); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse); + break; + case If_kind: + CALL(astfold_expr, expr_ty, node_->v.If.test); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse); + break; + case With_kind: + CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body); + break; + case AsyncWith_kind: + CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body); + break; + case Raise_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc); + CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause); + break; + case Try_kind: + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body); + CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody); + break; + case Assert_kind: + CALL(astfold_expr, expr_ty, node_->v.Assert.test); + CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg); + break; + case Expr_kind: + CALL(astfold_expr, expr_ty, node_->v.Expr.value); + break; + default: + break; + } + return 1; +} + +static int +astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_) +{ + switch (node_->kind) { + case ExceptHandler_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type); + CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body); + break; + default: + break; + } + return 1; +} + +static int +astfold_withitem(withitem_ty node_, PyArena* ctx_) +{ + CALL(astfold_expr, expr_ty, node_->context_expr); + CALL_OPT(astfold_expr, expr_ty, node_->optional_vars); + return 1; +} + +#undef CALL +#undef CALL_OPT +#undef CALL_SEQ +#undef CALL_INT_SEQ + +int +_PyAST_Optimize(mod_ty mod, PyArena *arena) +{ + int ret = astfold_mod(mod, arena); + assert(ret || PyErr_Occurred()); + return ret; +} diff --git a/Python/compile.c b/Python/compile.c index a3fcd53e9a2..3fd849108cc 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -331,6 +331,10 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize; c.c_nestlevel = 0; + if (!_PyAST_Optimize(mod, arena)) { + goto finally; + } + c.c_st = PySymtable_BuildObject(mod, filename, c.c_future); if (c.c_st == NULL) { if (!PyErr_Occurred()) diff --git a/Python/importlib.h b/Python/importlib.h index f475c169ad8..7908ea8b6ab 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -1,7 +1,7 @@ /* Auto-generated by Programs/_freeze_importlib.c */ const unsigned char _Py_M__importlib[] = { 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,64,0,0,0,115,216,1,0,0,100,0,90,0,100,1, + 0,64,0,0,0,115,208,1,0,0,100,0,90,0,100,1, 97,1,100,2,100,3,132,0,90,2,100,4,100,5,132,0, 90,3,105,0,90,4,105,0,90,5,71,0,100,6,100,7, 132,0,100,7,101,6,131,3,90,7,71,0,100,8,100,9, @@ -14,7 +14,7 @@ const unsigned char _Py_M__importlib[] = { 90,17,100,30,100,31,132,0,90,18,71,0,100,32,100,33, 132,0,100,33,131,2,90,19,71,0,100,34,100,35,132,0, 100,35,131,2,90,20,100,1,100,1,100,36,156,2,100,37, - 100,38,132,2,90,21,100,95,100,39,100,40,132,1,90,22, + 100,38,132,2,90,21,100,96,100,39,100,40,132,1,90,22, 100,41,100,42,156,1,100,43,100,44,132,2,90,23,100,45, 100,46,132,0,90,24,100,47,100,48,132,0,90,25,100,49, 100,50,132,0,90,26,100,51,100,52,132,0,90,27,100,53, @@ -22,1803 +22,1802 @@ const unsigned char _Py_M__importlib[] = { 100,57,100,58,132,0,100,58,131,2,90,30,71,0,100,59, 100,60,132,0,100,60,131,2,90,31,71,0,100,61,100,62, 132,0,100,62,131,2,90,32,100,63,100,64,132,0,90,33, - 100,65,100,66,132,0,90,34,100,96,100,67,100,68,132,1, + 100,65,100,66,132,0,90,34,100,97,100,67,100,68,132,1, 90,35,100,69,100,70,132,0,90,36,100,71,90,37,101,37, 100,72,23,0,90,38,100,73,100,74,132,0,90,39,101,40, - 131,0,90,41,100,75,100,76,132,0,90,42,100,97,100,78, + 131,0,90,41,100,75,100,76,132,0,90,42,100,98,100,78, 100,79,132,1,90,43,100,41,100,80,156,1,100,81,100,82, - 132,2,90,44,100,83,100,84,132,0,90,45,100,1,100,1, - 102,0,100,77,102,4,100,85,100,86,132,1,90,46,100,87, - 100,88,132,0,90,47,100,89,100,90,132,0,90,48,100,91, - 100,92,132,0,90,49,100,93,100,94,132,0,90,50,100,1, - 83,0,41,98,97,83,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, - 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,78,99,2,0, - 0,0,0,0,0,0,3,0,0,0,7,0,0,0,67,0, - 0,0,115,60,0,0,0,120,40,100,6,68,0,93,32,125, - 2,116,0,124,1,124,2,131,2,114,6,116,1,124,0,124, - 2,116,2,124,1,124,2,131,2,131,3,1,0,113,6,87, - 0,124,0,106,3,160,4,124,1,106,3,161,1,1,0,100, - 5,83,0,41,7,122,47,83,105,109,112,108,101,32,115,117, - 98,115,116,105,116,117,116,101,32,102,111,114,32,102,117,110, - 99,116,111,111,108,115,46,117,112,100,97,116,101,95,119,114, - 97,112,112,101,114,46,218,10,95,95,109,111,100,117,108,101, - 95,95,218,8,95,95,110,97,109,101,95,95,218,12,95,95, - 113,117,97,108,110,97,109,101,95,95,218,7,95,95,100,111, - 99,95,95,78,41,4,114,0,0,0,0,114,1,0,0,0, - 114,2,0,0,0,114,3,0,0,0,41,5,218,7,104,97, - 115,97,116,116,114,218,7,115,101,116,97,116,116,114,218,7, - 103,101,116,97,116,116,114,218,8,95,95,100,105,99,116,95, - 95,218,6,117,112,100,97,116,101,41,3,90,3,110,101,119, - 90,3,111,108,100,218,7,114,101,112,108,97,99,101,169,0, - 114,10,0,0,0,250,29,60,102,114,111,122,101,110,32,105, - 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, - 114,97,112,62,218,5,95,119,114,97,112,27,0,0,0,115, - 8,0,0,0,0,2,10,1,10,1,22,1,114,12,0,0, - 0,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, - 0,0,67,0,0,0,115,12,0,0,0,116,0,116,1,131, - 1,124,0,131,1,83,0,41,1,78,41,2,218,4,116,121, - 112,101,218,3,115,121,115,41,1,218,4,110,97,109,101,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,11, - 95,110,101,119,95,109,111,100,117,108,101,35,0,0,0,115, - 2,0,0,0,0,1,114,16,0,0,0,99,0,0,0,0, - 0,0,0,0,0,0,0,0,1,0,0,0,64,0,0,0, - 115,12,0,0,0,101,0,90,1,100,0,90,2,100,1,83, - 0,41,2,218,14,95,68,101,97,100,108,111,99,107,69,114, - 114,111,114,78,41,3,114,1,0,0,0,114,0,0,0,0, - 114,2,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,17,0,0,0,48,0, - 0,0,115,2,0,0,0,8,1,114,17,0,0,0,99,0, - 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,64, - 0,0,0,115,56,0,0,0,101,0,90,1,100,0,90,2, - 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, - 132,0,90,5,100,6,100,7,132,0,90,6,100,8,100,9, - 132,0,90,7,100,10,100,11,132,0,90,8,100,12,83,0, - 41,13,218,11,95,77,111,100,117,108,101,76,111,99,107,122, - 169,65,32,114,101,99,117,114,115,105,118,101,32,108,111,99, - 107,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110, - 32,119,104,105,99,104,32,105,115,32,97,98,108,101,32,116, - 111,32,100,101,116,101,99,116,32,100,101,97,100,108,111,99, - 107,115,10,32,32,32,32,40,101,46,103,46,32,116,104,114, - 101,97,100,32,49,32,116,114,121,105,110,103,32,116,111,32, - 116,97,107,101,32,108,111,99,107,115,32,65,32,116,104,101, - 110,32,66,44,32,97,110,100,32,116,104,114,101,97,100,32, - 50,32,116,114,121,105,110,103,32,116,111,10,32,32,32,32, - 116,97,107,101,32,108,111,99,107,115,32,66,32,116,104,101, - 110,32,65,41,46,10,32,32,32,32,99,2,0,0,0,0, - 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, - 48,0,0,0,116,0,160,1,161,0,124,0,95,2,116,0, - 160,1,161,0,124,0,95,3,124,1,124,0,95,4,100,0, - 124,0,95,5,100,1,124,0,95,6,100,1,124,0,95,7, - 100,0,83,0,41,2,78,233,0,0,0,0,41,8,218,7, - 95,116,104,114,101,97,100,90,13,97,108,108,111,99,97,116, - 101,95,108,111,99,107,218,4,108,111,99,107,218,6,119,97, - 107,101,117,112,114,15,0,0,0,218,5,111,119,110,101,114, - 218,5,99,111,117,110,116,218,7,119,97,105,116,101,114,115, - 41,2,218,4,115,101,108,102,114,15,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,218,8,95,95, - 105,110,105,116,95,95,58,0,0,0,115,12,0,0,0,0, - 1,10,1,10,1,6,1,6,1,6,1,122,20,95,77,111, - 100,117,108,101,76,111,99,107,46,95,95,105,110,105,116,95, - 95,99,1,0,0,0,0,0,0,0,4,0,0,0,3,0, - 0,0,67,0,0,0,115,64,0,0,0,116,0,160,1,161, - 0,125,1,124,0,106,2,125,2,120,44,116,3,160,4,124, - 2,161,1,125,3,124,3,100,0,107,8,114,38,100,1,83, - 0,124,3,106,2,125,2,124,2,124,1,107,2,114,16,100, - 2,83,0,113,16,87,0,100,0,83,0,41,3,78,70,84, - 41,5,114,20,0,0,0,218,9,103,101,116,95,105,100,101, - 110,116,114,23,0,0,0,218,12,95,98,108,111,99,107,105, - 110,103,95,111,110,218,3,103,101,116,41,4,114,26,0,0, - 0,90,2,109,101,218,3,116,105,100,114,21,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,12, - 104,97,115,95,100,101,97,100,108,111,99,107,66,0,0,0, - 115,18,0,0,0,0,2,8,1,6,1,2,1,10,1,8, - 1,4,1,6,1,8,1,122,24,95,77,111,100,117,108,101, - 76,111,99,107,46,104,97,115,95,100,101,97,100,108,111,99, - 107,99,1,0,0,0,0,0,0,0,2,0,0,0,16,0, - 0,0,67,0,0,0,115,168,0,0,0,116,0,160,1,161, - 0,125,1,124,0,116,2,124,1,60,0,122,138,120,132,124, - 0,106,3,143,96,1,0,124,0,106,4,100,1,107,2,115, - 48,124,0,106,5,124,1,107,2,114,72,124,1,124,0,95, - 5,124,0,4,0,106,4,100,2,55,0,2,0,95,4,100, - 3,83,0,124,0,160,6,161,0,114,92,116,7,100,4,124, - 0,22,0,131,1,130,1,124,0,106,8,160,9,100,5,161, - 1,114,118,124,0,4,0,106,10,100,2,55,0,2,0,95, - 10,87,0,100,6,81,0,82,0,88,0,124,0,106,8,160, - 9,161,0,1,0,124,0,106,8,160,11,161,0,1,0,113, - 20,87,0,87,0,100,6,116,2,124,1,61,0,88,0,100, - 6,83,0,41,7,122,185,10,32,32,32,32,32,32,32,32, - 65,99,113,117,105,114,101,32,116,104,101,32,109,111,100,117, - 108,101,32,108,111,99,107,46,32,32,73,102,32,97,32,112, - 111,116,101,110,116,105,97,108,32,100,101,97,100,108,111,99, - 107,32,105,115,32,100,101,116,101,99,116,101,100,44,10,32, - 32,32,32,32,32,32,32,97,32,95,68,101,97,100,108,111, - 99,107,69,114,114,111,114,32,105,115,32,114,97,105,115,101, - 100,46,10,32,32,32,32,32,32,32,32,79,116,104,101,114, - 119,105,115,101,44,32,116,104,101,32,108,111,99,107,32,105, - 115,32,97,108,119,97,121,115,32,97,99,113,117,105,114,101, - 100,32,97,110,100,32,84,114,117,101,32,105,115,32,114,101, - 116,117,114,110,101,100,46,10,32,32,32,32,32,32,32,32, - 114,19,0,0,0,233,1,0,0,0,84,122,23,100,101,97, - 100,108,111,99,107,32,100,101,116,101,99,116,101,100,32,98, - 121,32,37,114,70,78,41,12,114,20,0,0,0,114,28,0, - 0,0,114,29,0,0,0,114,21,0,0,0,114,24,0,0, - 0,114,23,0,0,0,114,32,0,0,0,114,17,0,0,0, - 114,22,0,0,0,218,7,97,99,113,117,105,114,101,114,25, - 0,0,0,218,7,114,101,108,101,97,115,101,41,2,114,26, - 0,0,0,114,31,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,34,0,0,0,78,0,0,0, - 115,32,0,0,0,0,6,8,1,8,1,2,1,2,1,8, - 1,20,1,6,1,14,1,4,1,8,1,12,1,12,1,24, - 2,10,1,18,2,122,19,95,77,111,100,117,108,101,76,111, - 99,107,46,97,99,113,117,105,114,101,99,1,0,0,0,0, - 0,0,0,2,0,0,0,10,0,0,0,67,0,0,0,115, - 122,0,0,0,116,0,160,1,161,0,125,1,124,0,106,2, - 143,98,1,0,124,0,106,3,124,1,107,3,114,34,116,4, - 100,1,131,1,130,1,124,0,106,5,100,2,107,4,115,48, - 116,6,130,1,124,0,4,0,106,5,100,3,56,0,2,0, - 95,5,124,0,106,5,100,2,107,2,114,108,100,0,124,0, - 95,3,124,0,106,7,114,108,124,0,4,0,106,7,100,3, - 56,0,2,0,95,7,124,0,106,8,160,9,161,0,1,0, - 87,0,100,0,81,0,82,0,88,0,100,0,83,0,41,4, - 78,122,31,99,97,110,110,111,116,32,114,101,108,101,97,115, - 101,32,117,110,45,97,99,113,117,105,114,101,100,32,108,111, - 99,107,114,19,0,0,0,114,33,0,0,0,41,10,114,20, - 0,0,0,114,28,0,0,0,114,21,0,0,0,114,23,0, - 0,0,218,12,82,117,110,116,105,109,101,69,114,114,111,114, - 114,24,0,0,0,218,14,65,115,115,101,114,116,105,111,110, - 69,114,114,111,114,114,25,0,0,0,114,22,0,0,0,114, - 35,0,0,0,41,2,114,26,0,0,0,114,31,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 35,0,0,0,103,0,0,0,115,22,0,0,0,0,1,8, - 1,8,1,10,1,8,1,14,1,14,1,10,1,6,1,6, - 1,14,1,122,19,95,77,111,100,117,108,101,76,111,99,107, - 46,114,101,108,101,97,115,101,99,1,0,0,0,0,0,0, - 0,1,0,0,0,5,0,0,0,67,0,0,0,115,18,0, - 0,0,100,1,160,0,124,0,106,1,116,2,124,0,131,1, - 161,2,83,0,41,2,78,122,23,95,77,111,100,117,108,101, - 76,111,99,107,40,123,33,114,125,41,32,97,116,32,123,125, - 41,3,218,6,102,111,114,109,97,116,114,15,0,0,0,218, - 2,105,100,41,1,114,26,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,8,95,95,114,101,112, - 114,95,95,116,0,0,0,115,2,0,0,0,0,1,122,20, - 95,77,111,100,117,108,101,76,111,99,107,46,95,95,114,101, - 112,114,95,95,78,41,9,114,1,0,0,0,114,0,0,0, - 0,114,2,0,0,0,114,3,0,0,0,114,27,0,0,0, - 114,32,0,0,0,114,34,0,0,0,114,35,0,0,0,114, - 40,0,0,0,114,10,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,18,0,0,0,52,0,0, - 0,115,10,0,0,0,12,6,8,8,8,12,8,25,8,13, - 114,18,0,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,64,0,0,0,115,48,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, - 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, - 0,90,6,100,8,100,9,132,0,90,7,100,10,83,0,41, - 11,218,16,95,68,117,109,109,121,77,111,100,117,108,101,76, - 111,99,107,122,86,65,32,115,105,109,112,108,101,32,95,77, - 111,100,117,108,101,76,111,99,107,32,101,113,117,105,118,97, - 108,101,110,116,32,102,111,114,32,80,121,116,104,111,110,32, - 98,117,105,108,100,115,32,119,105,116,104,111,117,116,10,32, - 32,32,32,109,117,108,116,105,45,116,104,114,101,97,100,105, - 110,103,32,115,117,112,112,111,114,116,46,99,2,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 115,16,0,0,0,124,1,124,0,95,0,100,1,124,0,95, - 1,100,0,83,0,41,2,78,114,19,0,0,0,41,2,114, - 15,0,0,0,114,24,0,0,0,41,2,114,26,0,0,0, + 132,2,90,44,100,83,100,84,132,0,90,45,100,99,100,86, + 100,87,132,1,90,46,100,88,100,89,132,0,90,47,100,90, + 100,91,132,0,90,48,100,92,100,93,132,0,90,49,100,94, + 100,95,132,0,90,50,100,1,83,0,41,100,97,83,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,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,78,99,2,0,0,0,0,0,0,0,3,0, + 0,0,7,0,0,0,67,0,0,0,115,60,0,0,0,120, + 40,100,6,68,0,93,32,125,2,116,0,124,1,124,2,131, + 2,114,6,116,1,124,0,124,2,116,2,124,1,124,2,131, + 2,131,3,1,0,113,6,87,0,124,0,106,3,160,4,124, + 1,106,3,161,1,1,0,100,5,83,0,41,7,122,47,83, + 105,109,112,108,101,32,115,117,98,115,116,105,116,117,116,101, + 32,102,111,114,32,102,117,110,99,116,111,111,108,115,46,117, + 112,100,97,116,101,95,119,114,97,112,112,101,114,46,218,10, + 95,95,109,111,100,117,108,101,95,95,218,8,95,95,110,97, + 109,101,95,95,218,12,95,95,113,117,97,108,110,97,109,101, + 95,95,218,7,95,95,100,111,99,95,95,78,41,4,114,0, + 0,0,0,114,1,0,0,0,114,2,0,0,0,114,3,0, + 0,0,41,5,218,7,104,97,115,97,116,116,114,218,7,115, + 101,116,97,116,116,114,218,7,103,101,116,97,116,116,114,218, + 8,95,95,100,105,99,116,95,95,218,6,117,112,100,97,116, + 101,41,3,90,3,110,101,119,90,3,111,108,100,218,7,114, + 101,112,108,97,99,101,169,0,114,10,0,0,0,250,29,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,62,218,5,95,119, + 114,97,112,27,0,0,0,115,8,0,0,0,0,2,10,1, + 10,1,22,1,114,12,0,0,0,99,1,0,0,0,0,0, + 0,0,1,0,0,0,2,0,0,0,67,0,0,0,115,12, + 0,0,0,116,0,116,1,131,1,124,0,131,1,83,0,41, + 1,78,41,2,218,4,116,121,112,101,218,3,115,121,115,41, + 1,218,4,110,97,109,101,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,218,11,95,110,101,119,95,109,111,100, + 117,108,101,35,0,0,0,115,2,0,0,0,0,1,114,16, + 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 1,0,0,0,64,0,0,0,115,12,0,0,0,101,0,90, + 1,100,0,90,2,100,1,83,0,41,2,218,14,95,68,101, + 97,100,108,111,99,107,69,114,114,111,114,78,41,3,114,1, + 0,0,0,114,0,0,0,0,114,2,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,17,0,0,0,48,0,0,0,115,2,0,0,0,8, + 1,114,17,0,0,0,99,0,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,64,0,0,0,115,56,0,0,0, + 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, + 132,0,90,4,100,4,100,5,132,0,90,5,100,6,100,7, + 132,0,90,6,100,8,100,9,132,0,90,7,100,10,100,11, + 132,0,90,8,100,12,83,0,41,13,218,11,95,77,111,100, + 117,108,101,76,111,99,107,122,169,65,32,114,101,99,117,114, + 115,105,118,101,32,108,111,99,107,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,119,104,105,99,104,32,105, + 115,32,97,98,108,101,32,116,111,32,100,101,116,101,99,116, + 32,100,101,97,100,108,111,99,107,115,10,32,32,32,32,40, + 101,46,103,46,32,116,104,114,101,97,100,32,49,32,116,114, + 121,105,110,103,32,116,111,32,116,97,107,101,32,108,111,99, + 107,115,32,65,32,116,104,101,110,32,66,44,32,97,110,100, + 32,116,104,114,101,97,100,32,50,32,116,114,121,105,110,103, + 32,116,111,10,32,32,32,32,116,97,107,101,32,108,111,99, + 107,115,32,66,32,116,104,101,110,32,65,41,46,10,32,32, + 32,32,99,2,0,0,0,0,0,0,0,2,0,0,0,2, + 0,0,0,67,0,0,0,115,48,0,0,0,116,0,160,1, + 161,0,124,0,95,2,116,0,160,1,161,0,124,0,95,3, + 124,1,124,0,95,4,100,0,124,0,95,5,100,1,124,0, + 95,6,100,1,124,0,95,7,100,0,83,0,41,2,78,233, + 0,0,0,0,41,8,218,7,95,116,104,114,101,97,100,90, + 13,97,108,108,111,99,97,116,101,95,108,111,99,107,218,4, + 108,111,99,107,218,6,119,97,107,101,117,112,114,15,0,0, + 0,218,5,111,119,110,101,114,218,5,99,111,117,110,116,218, + 7,119,97,105,116,101,114,115,41,2,218,4,115,101,108,102, 114,15,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,27,0,0,0,124,0,0,0,115,4,0, - 0,0,0,1,6,1,122,25,95,68,117,109,109,121,77,111, - 100,117,108,101,76,111,99,107,46,95,95,105,110,105,116,95, - 95,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,115,18,0,0,0,124,0,4,0,106, - 0,100,1,55,0,2,0,95,0,100,2,83,0,41,3,78, - 114,33,0,0,0,84,41,1,114,24,0,0,0,41,1,114, - 26,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,34,0,0,0,128,0,0,0,115,4,0,0, - 0,0,1,14,1,122,24,95,68,117,109,109,121,77,111,100, - 117,108,101,76,111,99,107,46,97,99,113,117,105,114,101,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,36,0,0,0,124,0,106,0,100,1,107, - 2,114,18,116,1,100,2,131,1,130,1,124,0,4,0,106, - 0,100,3,56,0,2,0,95,0,100,0,83,0,41,4,78, - 114,19,0,0,0,122,31,99,97,110,110,111,116,32,114,101, - 108,101,97,115,101,32,117,110,45,97,99,113,117,105,114,101, - 100,32,108,111,99,107,114,33,0,0,0,41,2,114,24,0, - 0,0,114,36,0,0,0,41,1,114,26,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,35,0, - 0,0,132,0,0,0,115,6,0,0,0,0,1,10,1,8, - 1,122,24,95,68,117,109,109,121,77,111,100,117,108,101,76, - 111,99,107,46,114,101,108,101,97,115,101,99,1,0,0,0, - 0,0,0,0,1,0,0,0,5,0,0,0,67,0,0,0, - 115,18,0,0,0,100,1,160,0,124,0,106,1,116,2,124, - 0,131,1,161,2,83,0,41,2,78,122,28,95,68,117,109, - 109,121,77,111,100,117,108,101,76,111,99,107,40,123,33,114, - 125,41,32,97,116,32,123,125,41,3,114,38,0,0,0,114, - 15,0,0,0,114,39,0,0,0,41,1,114,26,0,0,0, + 11,0,0,0,218,8,95,95,105,110,105,116,95,95,58,0, + 0,0,115,12,0,0,0,0,1,10,1,10,1,6,1,6, + 1,6,1,122,20,95,77,111,100,117,108,101,76,111,99,107, + 46,95,95,105,110,105,116,95,95,99,1,0,0,0,0,0, + 0,0,4,0,0,0,3,0,0,0,67,0,0,0,115,64, + 0,0,0,116,0,160,1,161,0,125,1,124,0,106,2,125, + 2,120,44,116,3,160,4,124,2,161,1,125,3,124,3,100, + 0,107,8,114,38,100,1,83,0,124,3,106,2,125,2,124, + 2,124,1,107,2,114,16,100,2,83,0,113,16,87,0,100, + 0,83,0,41,3,78,70,84,41,5,114,20,0,0,0,218, + 9,103,101,116,95,105,100,101,110,116,114,23,0,0,0,218, + 12,95,98,108,111,99,107,105,110,103,95,111,110,218,3,103, + 101,116,41,4,114,26,0,0,0,90,2,109,101,218,3,116, + 105,100,114,21,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,218,12,104,97,115,95,100,101,97,100, + 108,111,99,107,66,0,0,0,115,18,0,0,0,0,2,8, + 1,6,1,2,1,10,1,8,1,4,1,6,1,8,1,122, + 24,95,77,111,100,117,108,101,76,111,99,107,46,104,97,115, + 95,100,101,97,100,108,111,99,107,99,1,0,0,0,0,0, + 0,0,2,0,0,0,16,0,0,0,67,0,0,0,115,168, + 0,0,0,116,0,160,1,161,0,125,1,124,0,116,2,124, + 1,60,0,122,138,120,132,124,0,106,3,143,96,1,0,124, + 0,106,4,100,1,107,2,115,48,124,0,106,5,124,1,107, + 2,114,72,124,1,124,0,95,5,124,0,4,0,106,4,100, + 2,55,0,2,0,95,4,100,3,83,0,124,0,160,6,161, + 0,114,92,116,7,100,4,124,0,22,0,131,1,130,1,124, + 0,106,8,160,9,100,5,161,1,114,118,124,0,4,0,106, + 10,100,2,55,0,2,0,95,10,87,0,100,6,81,0,82, + 0,88,0,124,0,106,8,160,9,161,0,1,0,124,0,106, + 8,160,11,161,0,1,0,113,20,87,0,87,0,100,6,116, + 2,124,1,61,0,88,0,100,6,83,0,41,7,122,185,10, + 32,32,32,32,32,32,32,32,65,99,113,117,105,114,101,32, + 116,104,101,32,109,111,100,117,108,101,32,108,111,99,107,46, + 32,32,73,102,32,97,32,112,111,116,101,110,116,105,97,108, + 32,100,101,97,100,108,111,99,107,32,105,115,32,100,101,116, + 101,99,116,101,100,44,10,32,32,32,32,32,32,32,32,97, + 32,95,68,101,97,100,108,111,99,107,69,114,114,111,114,32, + 105,115,32,114,97,105,115,101,100,46,10,32,32,32,32,32, + 32,32,32,79,116,104,101,114,119,105,115,101,44,32,116,104, + 101,32,108,111,99,107,32,105,115,32,97,108,119,97,121,115, + 32,97,99,113,117,105,114,101,100,32,97,110,100,32,84,114, + 117,101,32,105,115,32,114,101,116,117,114,110,101,100,46,10, + 32,32,32,32,32,32,32,32,114,19,0,0,0,233,1,0, + 0,0,84,122,23,100,101,97,100,108,111,99,107,32,100,101, + 116,101,99,116,101,100,32,98,121,32,37,114,70,78,41,12, + 114,20,0,0,0,114,28,0,0,0,114,29,0,0,0,114, + 21,0,0,0,114,24,0,0,0,114,23,0,0,0,114,32, + 0,0,0,114,17,0,0,0,114,22,0,0,0,218,7,97, + 99,113,117,105,114,101,114,25,0,0,0,218,7,114,101,108, + 101,97,115,101,41,2,114,26,0,0,0,114,31,0,0,0, 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 40,0,0,0,137,0,0,0,115,2,0,0,0,0,1,122, - 25,95,68,117,109,109,121,77,111,100,117,108,101,76,111,99, - 107,46,95,95,114,101,112,114,95,95,78,41,8,114,1,0, - 0,0,114,0,0,0,0,114,2,0,0,0,114,3,0,0, - 0,114,27,0,0,0,114,34,0,0,0,114,35,0,0,0, - 114,40,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,41,0,0,0,120,0, - 0,0,115,8,0,0,0,12,4,8,4,8,4,8,5,114, - 41,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,64,0,0,0,115,36,0,0,0,101,0, - 90,1,100,0,90,2,100,1,100,2,132,0,90,3,100,3, - 100,4,132,0,90,4,100,5,100,6,132,0,90,5,100,7, - 83,0,41,8,218,18,95,77,111,100,117,108,101,76,111,99, - 107,77,97,110,97,103,101,114,99,2,0,0,0,0,0,0, - 0,2,0,0,0,2,0,0,0,67,0,0,0,115,16,0, - 0,0,124,1,124,0,95,0,100,0,124,0,95,1,100,0, - 83,0,41,1,78,41,2,218,5,95,110,97,109,101,218,5, - 95,108,111,99,107,41,2,114,26,0,0,0,114,15,0,0, + 34,0,0,0,78,0,0,0,115,32,0,0,0,0,6,8, + 1,8,1,2,1,2,1,8,1,20,1,6,1,14,1,4, + 1,8,1,12,1,12,1,24,2,10,1,18,2,122,19,95, + 77,111,100,117,108,101,76,111,99,107,46,97,99,113,117,105, + 114,101,99,1,0,0,0,0,0,0,0,2,0,0,0,10, + 0,0,0,67,0,0,0,115,122,0,0,0,116,0,160,1, + 161,0,125,1,124,0,106,2,143,98,1,0,124,0,106,3, + 124,1,107,3,114,34,116,4,100,1,131,1,130,1,124,0, + 106,5,100,2,107,4,115,48,116,6,130,1,124,0,4,0, + 106,5,100,3,56,0,2,0,95,5,124,0,106,5,100,2, + 107,2,114,108,100,0,124,0,95,3,124,0,106,7,114,108, + 124,0,4,0,106,7,100,3,56,0,2,0,95,7,124,0, + 106,8,160,9,161,0,1,0,87,0,100,0,81,0,82,0, + 88,0,100,0,83,0,41,4,78,122,31,99,97,110,110,111, + 116,32,114,101,108,101,97,115,101,32,117,110,45,97,99,113, + 117,105,114,101,100,32,108,111,99,107,114,19,0,0,0,114, + 33,0,0,0,41,10,114,20,0,0,0,114,28,0,0,0, + 114,21,0,0,0,114,23,0,0,0,218,12,82,117,110,116, + 105,109,101,69,114,114,111,114,114,24,0,0,0,218,14,65, + 115,115,101,114,116,105,111,110,69,114,114,111,114,114,25,0, + 0,0,114,22,0,0,0,114,35,0,0,0,41,2,114,26, + 0,0,0,114,31,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,35,0,0,0,103,0,0,0, + 115,22,0,0,0,0,1,8,1,8,1,10,1,8,1,14, + 1,14,1,10,1,6,1,6,1,14,1,122,19,95,77,111, + 100,117,108,101,76,111,99,107,46,114,101,108,101,97,115,101, + 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, + 0,67,0,0,0,115,18,0,0,0,100,1,160,0,124,0, + 106,1,116,2,124,0,131,1,161,2,83,0,41,2,78,122, + 23,95,77,111,100,117,108,101,76,111,99,107,40,123,33,114, + 125,41,32,97,116,32,123,125,41,3,218,6,102,111,114,109, + 97,116,114,15,0,0,0,218,2,105,100,41,1,114,26,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,218,8,95,95,114,101,112,114,95,95,116,0,0,0,115, + 2,0,0,0,0,1,122,20,95,77,111,100,117,108,101,76, + 111,99,107,46,95,95,114,101,112,114,95,95,78,41,9,114, + 1,0,0,0,114,0,0,0,0,114,2,0,0,0,114,3, + 0,0,0,114,27,0,0,0,114,32,0,0,0,114,34,0, + 0,0,114,35,0,0,0,114,40,0,0,0,114,10,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,27,0,0,0,143,0,0,0,115,4,0,0,0,0,1, - 6,1,122,27,95,77,111,100,117,108,101,76,111,99,107,77, - 97,110,97,103,101,114,46,95,95,105,110,105,116,95,95,99, - 1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, - 67,0,0,0,115,26,0,0,0,116,0,124,0,106,1,131, - 1,124,0,95,2,124,0,106,2,160,3,161,0,1,0,100, - 0,83,0,41,1,78,41,4,218,16,95,103,101,116,95,109, - 111,100,117,108,101,95,108,111,99,107,114,43,0,0,0,114, - 44,0,0,0,114,34,0,0,0,41,1,114,26,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, - 9,95,95,101,110,116,101,114,95,95,147,0,0,0,115,4, - 0,0,0,0,1,12,1,122,28,95,77,111,100,117,108,101, - 76,111,99,107,77,97,110,97,103,101,114,46,95,95,101,110, - 116,101,114,95,95,99,1,0,0,0,0,0,0,0,3,0, - 0,0,2,0,0,0,79,0,0,0,115,14,0,0,0,124, - 0,106,0,160,1,161,0,1,0,100,0,83,0,41,1,78, - 41,2,114,44,0,0,0,114,35,0,0,0,41,3,114,26, - 0,0,0,218,4,97,114,103,115,90,6,107,119,97,114,103, - 115,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,8,95,95,101,120,105,116,95,95,151,0,0,0,115,2, - 0,0,0,0,1,122,27,95,77,111,100,117,108,101,76,111, - 99,107,77,97,110,97,103,101,114,46,95,95,101,120,105,116, + 114,18,0,0,0,52,0,0,0,115,10,0,0,0,12,6, + 8,8,8,12,8,25,8,13,114,18,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, + 0,0,115,48,0,0,0,101,0,90,1,100,0,90,2,100, + 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, + 0,90,5,100,6,100,7,132,0,90,6,100,8,100,9,132, + 0,90,7,100,10,83,0,41,11,218,16,95,68,117,109,109, + 121,77,111,100,117,108,101,76,111,99,107,122,86,65,32,115, + 105,109,112,108,101,32,95,77,111,100,117,108,101,76,111,99, + 107,32,101,113,117,105,118,97,108,101,110,116,32,102,111,114, + 32,80,121,116,104,111,110,32,98,117,105,108,100,115,32,119, + 105,116,104,111,117,116,10,32,32,32,32,109,117,108,116,105, + 45,116,104,114,101,97,100,105,110,103,32,115,117,112,112,111, + 114,116,46,99,2,0,0,0,0,0,0,0,2,0,0,0, + 2,0,0,0,67,0,0,0,115,16,0,0,0,124,1,124, + 0,95,0,100,1,124,0,95,1,100,0,83,0,41,2,78, + 114,19,0,0,0,41,2,114,15,0,0,0,114,24,0,0, + 0,41,2,114,26,0,0,0,114,15,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,27,0,0, + 0,124,0,0,0,115,4,0,0,0,0,1,6,1,122,25, + 95,68,117,109,109,121,77,111,100,117,108,101,76,111,99,107, + 46,95,95,105,110,105,116,95,95,99,1,0,0,0,0,0, + 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,18, + 0,0,0,124,0,4,0,106,0,100,1,55,0,2,0,95, + 0,100,2,83,0,41,3,78,114,33,0,0,0,84,41,1, + 114,24,0,0,0,41,1,114,26,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,34,0,0,0, + 128,0,0,0,115,4,0,0,0,0,1,14,1,122,24,95, + 68,117,109,109,121,77,111,100,117,108,101,76,111,99,107,46, + 97,99,113,117,105,114,101,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,36,0,0, + 0,124,0,106,0,100,1,107,2,114,18,116,1,100,2,131, + 1,130,1,124,0,4,0,106,0,100,3,56,0,2,0,95, + 0,100,0,83,0,41,4,78,114,19,0,0,0,122,31,99, + 97,110,110,111,116,32,114,101,108,101,97,115,101,32,117,110, + 45,97,99,113,117,105,114,101,100,32,108,111,99,107,114,33, + 0,0,0,41,2,114,24,0,0,0,114,36,0,0,0,41, + 1,114,26,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,35,0,0,0,132,0,0,0,115,6, + 0,0,0,0,1,10,1,8,1,122,24,95,68,117,109,109, + 121,77,111,100,117,108,101,76,111,99,107,46,114,101,108,101, + 97,115,101,99,1,0,0,0,0,0,0,0,1,0,0,0, + 5,0,0,0,67,0,0,0,115,18,0,0,0,100,1,160, + 0,124,0,106,1,116,2,124,0,131,1,161,2,83,0,41, + 2,78,122,28,95,68,117,109,109,121,77,111,100,117,108,101, + 76,111,99,107,40,123,33,114,125,41,32,97,116,32,123,125, + 41,3,114,38,0,0,0,114,15,0,0,0,114,39,0,0, + 0,41,1,114,26,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,40,0,0,0,137,0,0,0, + 115,2,0,0,0,0,1,122,25,95,68,117,109,109,121,77, + 111,100,117,108,101,76,111,99,107,46,95,95,114,101,112,114, + 95,95,78,41,8,114,1,0,0,0,114,0,0,0,0,114, + 2,0,0,0,114,3,0,0,0,114,27,0,0,0,114,34, + 0,0,0,114,35,0,0,0,114,40,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,41,0,0,0,120,0,0,0,115,8,0,0,0,12, + 4,8,4,8,4,8,5,114,41,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, + 0,115,36,0,0,0,101,0,90,1,100,0,90,2,100,1, + 100,2,132,0,90,3,100,3,100,4,132,0,90,4,100,5, + 100,6,132,0,90,5,100,7,83,0,41,8,218,18,95,77, + 111,100,117,108,101,76,111,99,107,77,97,110,97,103,101,114, + 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, + 0,67,0,0,0,115,16,0,0,0,124,1,124,0,95,0, + 100,0,124,0,95,1,100,0,83,0,41,1,78,41,2,218, + 5,95,110,97,109,101,218,5,95,108,111,99,107,41,2,114, + 26,0,0,0,114,15,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,27,0,0,0,143,0,0, + 0,115,4,0,0,0,0,1,6,1,122,27,95,77,111,100, + 117,108,101,76,111,99,107,77,97,110,97,103,101,114,46,95, + 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, + 1,0,0,0,2,0,0,0,67,0,0,0,115,26,0,0, + 0,116,0,124,0,106,1,131,1,124,0,95,2,124,0,106, + 2,160,3,161,0,1,0,100,0,83,0,41,1,78,41,4, + 218,16,95,103,101,116,95,109,111,100,117,108,101,95,108,111, + 99,107,114,43,0,0,0,114,44,0,0,0,114,34,0,0, + 0,41,1,114,26,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,9,95,95,101,110,116,101,114, + 95,95,147,0,0,0,115,4,0,0,0,0,1,12,1,122, + 28,95,77,111,100,117,108,101,76,111,99,107,77,97,110,97, + 103,101,114,46,95,95,101,110,116,101,114,95,95,99,1,0, + 0,0,0,0,0,0,3,0,0,0,2,0,0,0,79,0, + 0,0,115,14,0,0,0,124,0,106,0,160,1,161,0,1, + 0,100,0,83,0,41,1,78,41,2,114,44,0,0,0,114, + 35,0,0,0,41,3,114,26,0,0,0,218,4,97,114,103, + 115,90,6,107,119,97,114,103,115,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,218,8,95,95,101,120,105,116, + 95,95,151,0,0,0,115,2,0,0,0,0,1,122,27,95, + 77,111,100,117,108,101,76,111,99,107,77,97,110,97,103,101, + 114,46,95,95,101,120,105,116,95,95,78,41,6,114,1,0, + 0,0,114,0,0,0,0,114,2,0,0,0,114,27,0,0, + 0,114,46,0,0,0,114,48,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 42,0,0,0,141,0,0,0,115,6,0,0,0,8,2,8, + 4,8,4,114,42,0,0,0,99,1,0,0,0,0,0,0, + 0,3,0,0,0,18,0,0,0,67,0,0,0,115,130,0, + 0,0,116,0,160,1,161,0,1,0,122,106,121,14,116,2, + 124,0,25,0,131,0,125,1,87,0,110,24,4,0,116,3, + 107,10,114,48,1,0,1,0,1,0,100,1,125,1,89,0, + 110,2,88,0,124,1,100,1,107,8,114,112,116,4,100,1, + 107,8,114,76,116,5,124,0,131,1,125,1,110,8,116,6, + 124,0,131,1,125,1,124,0,102,1,100,2,100,3,132,1, + 125,2,116,7,160,8,124,1,124,2,161,2,116,2,124,0, + 60,0,87,0,100,1,116,0,160,9,161,0,1,0,88,0, + 124,1,83,0,41,4,122,139,71,101,116,32,111,114,32,99, + 114,101,97,116,101,32,116,104,101,32,109,111,100,117,108,101, + 32,108,111,99,107,32,102,111,114,32,97,32,103,105,118,101, + 110,32,109,111,100,117,108,101,32,110,97,109,101,46,10,10, + 32,32,32,32,65,99,113,117,105,114,101,47,114,101,108,101, + 97,115,101,32,105,110,116,101,114,110,97,108,108,121,32,116, + 104,101,32,103,108,111,98,97,108,32,105,109,112,111,114,116, + 32,108,111,99,107,32,116,111,32,112,114,111,116,101,99,116, + 10,32,32,32,32,95,109,111,100,117,108,101,95,108,111,99, + 107,115,46,78,99,2,0,0,0,0,0,0,0,2,0,0, + 0,11,0,0,0,83,0,0,0,115,48,0,0,0,116,0, + 160,1,161,0,1,0,122,24,116,2,160,3,124,1,161,1, + 124,0,107,8,114,30,116,2,124,1,61,0,87,0,100,0, + 116,0,160,4,161,0,1,0,88,0,100,0,83,0,41,1, + 78,41,5,218,4,95,105,109,112,218,12,97,99,113,117,105, + 114,101,95,108,111,99,107,218,13,95,109,111,100,117,108,101, + 95,108,111,99,107,115,114,30,0,0,0,218,12,114,101,108, + 101,97,115,101,95,108,111,99,107,41,2,218,3,114,101,102, + 114,15,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,2,99,98,176,0,0,0,115,10,0,0, + 0,0,1,8,1,2,4,14,1,10,2,122,28,95,103,101, + 116,95,109,111,100,117,108,101,95,108,111,99,107,46,60,108, + 111,99,97,108,115,62,46,99,98,41,10,114,49,0,0,0, + 114,50,0,0,0,114,51,0,0,0,218,8,75,101,121,69, + 114,114,111,114,114,20,0,0,0,114,41,0,0,0,114,18, + 0,0,0,218,8,95,119,101,97,107,114,101,102,114,53,0, + 0,0,114,52,0,0,0,41,3,114,15,0,0,0,114,21, + 0,0,0,114,54,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,45,0,0,0,157,0,0,0, + 115,28,0,0,0,0,6,8,1,2,1,2,1,14,1,14, + 1,10,2,8,1,8,1,10,2,8,2,12,11,20,2,10, + 2,114,45,0,0,0,99,1,0,0,0,0,0,0,0,2, + 0,0,0,11,0,0,0,67,0,0,0,115,54,0,0,0, + 116,0,124,0,131,1,125,1,121,12,124,1,160,1,161,0, + 1,0,87,0,110,20,4,0,116,2,107,10,114,40,1,0, + 1,0,1,0,89,0,110,10,88,0,124,1,160,3,161,0, + 1,0,100,1,83,0,41,2,122,189,65,99,113,117,105,114, + 101,115,32,116,104,101,110,32,114,101,108,101,97,115,101,115, + 32,116,104,101,32,109,111,100,117,108,101,32,108,111,99,107, + 32,102,111,114,32,97,32,103,105,118,101,110,32,109,111,100, + 117,108,101,32,110,97,109,101,46,10,10,32,32,32,32,84, + 104,105,115,32,105,115,32,117,115,101,100,32,116,111,32,101, + 110,115,117,114,101,32,97,32,109,111,100,117,108,101,32,105, + 115,32,99,111,109,112,108,101,116,101,108,121,32,105,110,105, + 116,105,97,108,105,122,101,100,44,32,105,110,32,116,104,101, + 10,32,32,32,32,101,118,101,110,116,32,105,116,32,105,115, + 32,98,101,105,110,103,32,105,109,112,111,114,116,101,100,32, + 98,121,32,97,110,111,116,104,101,114,32,116,104,114,101,97, + 100,46,10,32,32,32,32,78,41,4,114,45,0,0,0,114, + 34,0,0,0,114,17,0,0,0,114,35,0,0,0,41,2, + 114,15,0,0,0,114,21,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,218,19,95,108,111,99,107, + 95,117,110,108,111,99,107,95,109,111,100,117,108,101,194,0, + 0,0,115,12,0,0,0,0,6,8,1,2,1,12,1,14, + 3,6,2,114,57,0,0,0,99,1,0,0,0,0,0,0, + 0,3,0,0,0,3,0,0,0,79,0,0,0,115,10,0, + 0,0,124,0,124,1,124,2,142,1,83,0,41,1,97,46, + 1,0,0,114,101,109,111,118,101,95,105,109,112,111,114,116, + 108,105,98,95,102,114,97,109,101,115,32,105,110,32,105,109, + 112,111,114,116,46,99,32,119,105,108,108,32,97,108,119,97, + 121,115,32,114,101,109,111,118,101,32,115,101,113,117,101,110, + 99,101,115,10,32,32,32,32,111,102,32,105,109,112,111,114, + 116,108,105,98,32,102,114,97,109,101,115,32,116,104,97,116, + 32,101,110,100,32,119,105,116,104,32,97,32,99,97,108,108, + 32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111, + 110,10,10,32,32,32,32,85,115,101,32,105,116,32,105,110, + 115,116,101,97,100,32,111,102,32,97,32,110,111,114,109,97, + 108,32,99,97,108,108,32,105,110,32,112,108,97,99,101,115, + 32,119,104,101,114,101,32,105,110,99,108,117,100,105,110,103, + 32,116,104,101,32,105,109,112,111,114,116,108,105,98,10,32, + 32,32,32,102,114,97,109,101,115,32,105,110,116,114,111,100, + 117,99,101,115,32,117,110,119,97,110,116,101,100,32,110,111, + 105,115,101,32,105,110,116,111,32,116,104,101,32,116,114,97, + 99,101,98,97,99,107,32,40,101,46,103,46,32,119,104,101, + 110,32,101,120,101,99,117,116,105,110,103,10,32,32,32,32, + 109,111,100,117,108,101,32,99,111,100,101,41,10,32,32,32, + 32,114,10,0,0,0,41,3,218,1,102,114,47,0,0,0, + 90,4,107,119,100,115,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,25,95,99,97,108,108,95,119,105,116, + 104,95,102,114,97,109,101,115,95,114,101,109,111,118,101,100, + 211,0,0,0,115,2,0,0,0,0,8,114,59,0,0,0, + 114,33,0,0,0,41,1,218,9,118,101,114,98,111,115,105, + 116,121,99,1,0,0,0,1,0,0,0,3,0,0,0,4, + 0,0,0,71,0,0,0,115,54,0,0,0,116,0,106,1, + 106,2,124,1,107,5,114,50,124,0,160,3,100,1,161,1, + 115,30,100,2,124,0,23,0,125,0,116,4,124,0,106,5, + 124,2,142,0,116,0,106,6,100,3,141,2,1,0,100,4, + 83,0,41,5,122,61,80,114,105,110,116,32,116,104,101,32, + 109,101,115,115,97,103,101,32,116,111,32,115,116,100,101,114, + 114,32,105,102,32,45,118,47,80,89,84,72,79,78,86,69, + 82,66,79,83,69,32,105,115,32,116,117,114,110,101,100,32, + 111,110,46,41,2,250,1,35,122,7,105,109,112,111,114,116, + 32,122,2,35,32,41,1,90,4,102,105,108,101,78,41,7, + 114,14,0,0,0,218,5,102,108,97,103,115,218,7,118,101, + 114,98,111,115,101,218,10,115,116,97,114,116,115,119,105,116, + 104,218,5,112,114,105,110,116,114,38,0,0,0,218,6,115, + 116,100,101,114,114,41,3,218,7,109,101,115,115,97,103,101, + 114,60,0,0,0,114,47,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,218,16,95,118,101,114,98, + 111,115,101,95,109,101,115,115,97,103,101,222,0,0,0,115, + 8,0,0,0,0,2,12,1,10,1,8,1,114,68,0,0, + 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,3,0,0,0,115,26,0,0,0,135,0,102,1,100, + 1,100,2,132,8,125,1,116,0,124,1,136,0,131,2,1, + 0,124,1,83,0,41,3,122,49,68,101,99,111,114,97,116, + 111,114,32,116,111,32,118,101,114,105,102,121,32,116,104,101, + 32,110,97,109,101,100,32,109,111,100,117,108,101,32,105,115, + 32,98,117,105,108,116,45,105,110,46,99,2,0,0,0,0, + 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, + 38,0,0,0,124,1,116,0,106,1,107,7,114,28,116,2, + 100,1,160,3,124,1,161,1,124,1,100,2,141,2,130,1, + 136,0,124,0,124,1,131,2,83,0,41,3,78,122,29,123, + 33,114,125,32,105,115,32,110,111,116,32,97,32,98,117,105, + 108,116,45,105,110,32,109,111,100,117,108,101,41,1,114,15, + 0,0,0,41,4,114,14,0,0,0,218,20,98,117,105,108, + 116,105,110,95,109,111,100,117,108,101,95,110,97,109,101,115, + 218,11,73,109,112,111,114,116,69,114,114,111,114,114,38,0, + 0,0,41,2,114,26,0,0,0,218,8,102,117,108,108,110, + 97,109,101,41,1,218,3,102,120,110,114,10,0,0,0,114, + 11,0,0,0,218,25,95,114,101,113,117,105,114,101,115,95, + 98,117,105,108,116,105,110,95,119,114,97,112,112,101,114,232, + 0,0,0,115,8,0,0,0,0,1,10,1,10,1,8,1, + 122,52,95,114,101,113,117,105,114,101,115,95,98,117,105,108, + 116,105,110,46,60,108,111,99,97,108,115,62,46,95,114,101, + 113,117,105,114,101,115,95,98,117,105,108,116,105,110,95,119, + 114,97,112,112,101,114,41,1,114,12,0,0,0,41,2,114, + 72,0,0,0,114,73,0,0,0,114,10,0,0,0,41,1, + 114,72,0,0,0,114,11,0,0,0,218,17,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,230,0,0, + 0,115,6,0,0,0,0,2,12,5,10,1,114,74,0,0, + 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,3,0,0,0,115,26,0,0,0,135,0,102,1,100, + 1,100,2,132,8,125,1,116,0,124,1,136,0,131,2,1, + 0,124,1,83,0,41,3,122,47,68,101,99,111,114,97,116, + 111,114,32,116,111,32,118,101,114,105,102,121,32,116,104,101, + 32,110,97,109,101,100,32,109,111,100,117,108,101,32,105,115, + 32,102,114,111,122,101,110,46,99,2,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,19,0,0,0,115,38,0, + 0,0,116,0,160,1,124,1,161,1,115,28,116,2,100,1, + 160,3,124,1,161,1,124,1,100,2,141,2,130,1,136,0, + 124,0,124,1,131,2,83,0,41,3,78,122,27,123,33,114, + 125,32,105,115,32,110,111,116,32,97,32,102,114,111,122,101, + 110,32,109,111,100,117,108,101,41,1,114,15,0,0,0,41, + 4,114,49,0,0,0,218,9,105,115,95,102,114,111,122,101, + 110,114,70,0,0,0,114,38,0,0,0,41,2,114,26,0, + 0,0,114,71,0,0,0,41,1,114,72,0,0,0,114,10, + 0,0,0,114,11,0,0,0,218,24,95,114,101,113,117,105, + 114,101,115,95,102,114,111,122,101,110,95,119,114,97,112,112, + 101,114,243,0,0,0,115,8,0,0,0,0,1,10,1,10, + 1,8,1,122,50,95,114,101,113,117,105,114,101,115,95,102, + 114,111,122,101,110,46,60,108,111,99,97,108,115,62,46,95, + 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,95, + 119,114,97,112,112,101,114,41,1,114,12,0,0,0,41,2, + 114,72,0,0,0,114,76,0,0,0,114,10,0,0,0,41, + 1,114,72,0,0,0,114,11,0,0,0,218,16,95,114,101, + 113,117,105,114,101,115,95,102,114,111,122,101,110,241,0,0, + 0,115,6,0,0,0,0,2,12,5,10,1,114,77,0,0, + 0,99,2,0,0,0,0,0,0,0,4,0,0,0,3,0, + 0,0,67,0,0,0,115,62,0,0,0,116,0,124,1,124, + 0,131,2,125,2,124,1,116,1,106,2,107,6,114,50,116, + 1,106,2,124,1,25,0,125,3,116,3,124,2,124,3,131, + 2,1,0,116,1,106,2,124,1,25,0,83,0,116,4,124, + 2,131,1,83,0,100,1,83,0,41,2,122,128,76,111,97, + 100,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, + 109,111,100,117,108,101,32,105,110,116,111,32,115,121,115,46, + 109,111,100,117,108,101,115,32,97,110,100,32,114,101,116,117, + 114,110,32,105,116,46,10,10,32,32,32,32,84,104,105,115, + 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, + 99,97,116,101,100,46,32,32,85,115,101,32,108,111,97,100, + 101,114,46,101,120,101,99,95,109,111,100,117,108,101,32,105, + 110,115,116,101,97,100,46,10,10,32,32,32,32,78,41,5, + 218,16,115,112,101,99,95,102,114,111,109,95,108,111,97,100, + 101,114,114,14,0,0,0,218,7,109,111,100,117,108,101,115, + 218,5,95,101,120,101,99,218,5,95,108,111,97,100,41,4, + 114,26,0,0,0,114,71,0,0,0,218,4,115,112,101,99, + 218,6,109,111,100,117,108,101,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,17,95,108,111,97,100,95,109, + 111,100,117,108,101,95,115,104,105,109,253,0,0,0,115,12, + 0,0,0,0,6,10,1,10,1,10,1,10,1,10,2,114, + 84,0,0,0,99,1,0,0,0,0,0,0,0,5,0,0, + 0,36,0,0,0,67,0,0,0,115,216,0,0,0,116,0, + 124,0,100,1,100,0,131,3,125,1,116,1,124,1,100,2, + 131,2,114,54,121,10,124,1,160,2,124,0,161,1,83,0, + 4,0,116,3,107,10,114,52,1,0,1,0,1,0,89,0, + 110,2,88,0,121,10,124,0,106,4,125,2,87,0,110,20, + 4,0,116,5,107,10,114,84,1,0,1,0,1,0,89,0, + 110,18,88,0,124,2,100,0,107,9,114,102,116,6,124,2, + 131,1,83,0,121,10,124,0,106,7,125,3,87,0,110,24, + 4,0,116,5,107,10,114,136,1,0,1,0,1,0,100,3, + 125,3,89,0,110,2,88,0,121,10,124,0,106,8,125,4, + 87,0,110,50,4,0,116,5,107,10,114,198,1,0,1,0, + 1,0,124,1,100,0,107,8,114,182,100,4,160,9,124,3, + 161,1,83,0,100,5,160,9,124,3,124,1,161,2,83,0, + 89,0,110,14,88,0,100,6,160,9,124,3,124,4,161,2, + 83,0,100,0,83,0,41,7,78,218,10,95,95,108,111,97, + 100,101,114,95,95,218,11,109,111,100,117,108,101,95,114,101, + 112,114,250,1,63,122,13,60,109,111,100,117,108,101,32,123, + 33,114,125,62,122,20,60,109,111,100,117,108,101,32,123,33, + 114,125,32,40,123,33,114,125,41,62,122,23,60,109,111,100, + 117,108,101,32,123,33,114,125,32,102,114,111,109,32,123,33, + 114,125,62,41,10,114,6,0,0,0,114,4,0,0,0,114, + 86,0,0,0,218,9,69,120,99,101,112,116,105,111,110,218, + 8,95,95,115,112,101,99,95,95,218,14,65,116,116,114,105, + 98,117,116,101,69,114,114,111,114,218,22,95,109,111,100,117, + 108,101,95,114,101,112,114,95,102,114,111,109,95,115,112,101, + 99,114,1,0,0,0,218,8,95,95,102,105,108,101,95,95, + 114,38,0,0,0,41,5,114,83,0,0,0,218,6,108,111, + 97,100,101,114,114,82,0,0,0,114,15,0,0,0,218,8, + 102,105,108,101,110,97,109,101,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,12,95,109,111,100,117,108,101, + 95,114,101,112,114,13,1,0,0,115,46,0,0,0,0,2, + 12,1,10,4,2,1,10,1,14,1,6,1,2,1,10,1, + 14,1,6,2,8,1,8,4,2,1,10,1,14,1,10,1, + 2,1,10,1,14,1,8,1,10,2,18,2,114,95,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,64,0,0,0,115,36,0,0,0,101,0,90,1,100, + 0,90,2,100,1,100,2,132,0,90,3,100,3,100,4,132, + 0,90,4,100,5,100,6,132,0,90,5,100,7,83,0,41, + 8,218,17,95,105,110,115,116,97,108,108,101,100,95,115,97, + 102,101,108,121,99,2,0,0,0,0,0,0,0,2,0,0, + 0,2,0,0,0,67,0,0,0,115,18,0,0,0,124,1, + 124,0,95,0,124,1,106,1,124,0,95,2,100,0,83,0, + 41,1,78,41,3,218,7,95,109,111,100,117,108,101,114,89, + 0,0,0,218,5,95,115,112,101,99,41,2,114,26,0,0, + 0,114,83,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,27,0,0,0,51,1,0,0,115,4, + 0,0,0,0,1,6,1,122,26,95,105,110,115,116,97,108, + 108,101,100,95,115,97,102,101,108,121,46,95,95,105,110,105, + 116,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,28,0,0,0,100,1,124, + 0,106,0,95,1,124,0,106,2,116,3,106,4,124,0,106, + 0,106,5,60,0,100,0,83,0,41,2,78,84,41,6,114, + 98,0,0,0,218,13,95,105,110,105,116,105,97,108,105,122, + 105,110,103,114,97,0,0,0,114,14,0,0,0,114,79,0, + 0,0,114,15,0,0,0,41,1,114,26,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,46,0, + 0,0,55,1,0,0,115,4,0,0,0,0,4,8,1,122, + 27,95,105,110,115,116,97,108,108,101,100,95,115,97,102,101, + 108,121,46,95,95,101,110,116,101,114,95,95,99,1,0,0, + 0,0,0,0,0,3,0,0,0,17,0,0,0,71,0,0, + 0,115,98,0,0,0,122,82,124,0,106,0,125,2,116,1, + 100,1,100,2,132,0,124,1,68,0,131,1,131,1,114,64, + 121,14,116,2,106,3,124,2,106,4,61,0,87,0,113,80, + 4,0,116,5,107,10,114,60,1,0,1,0,1,0,89,0, + 113,80,88,0,110,16,116,6,100,3,124,2,106,4,124,2, + 106,7,131,3,1,0,87,0,100,0,100,4,124,0,106,0, + 95,8,88,0,100,0,83,0,41,5,78,99,1,0,0,0, + 0,0,0,0,2,0,0,0,3,0,0,0,115,0,0,0, + 115,22,0,0,0,124,0,93,14,125,1,124,1,100,0,107, + 9,86,0,1,0,113,2,100,0,83,0,41,1,78,114,10, + 0,0,0,41,2,90,2,46,48,90,3,97,114,103,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,250,9,60, + 103,101,110,101,120,112,114,62,65,1,0,0,115,2,0,0, + 0,4,0,122,45,95,105,110,115,116,97,108,108,101,100,95, + 115,97,102,101,108,121,46,95,95,101,120,105,116,95,95,46, + 60,108,111,99,97,108,115,62,46,60,103,101,110,101,120,112, + 114,62,122,18,105,109,112,111,114,116,32,123,33,114,125,32, + 35,32,123,33,114,125,70,41,9,114,98,0,0,0,218,3, + 97,110,121,114,14,0,0,0,114,79,0,0,0,114,15,0, + 0,0,114,55,0,0,0,114,68,0,0,0,114,93,0,0, + 0,114,99,0,0,0,41,3,114,26,0,0,0,114,47,0, + 0,0,114,82,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,48,0,0,0,62,1,0,0,115, + 18,0,0,0,0,1,2,1,6,1,18,1,2,1,14,1, + 14,1,8,2,20,2,122,26,95,105,110,115,116,97,108,108, + 101,100,95,115,97,102,101,108,121,46,95,95,101,120,105,116, 95,95,78,41,6,114,1,0,0,0,114,0,0,0,0,114, 2,0,0,0,114,27,0,0,0,114,46,0,0,0,114,48, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,42,0,0,0,141,0,0,0, - 115,6,0,0,0,8,2,8,4,8,4,114,42,0,0,0, - 99,1,0,0,0,0,0,0,0,3,0,0,0,18,0,0, - 0,67,0,0,0,115,130,0,0,0,116,0,160,1,161,0, - 1,0,122,106,121,14,116,2,124,0,25,0,131,0,125,1, - 87,0,110,24,4,0,116,3,107,10,114,48,1,0,1,0, - 1,0,100,1,125,1,89,0,110,2,88,0,124,1,100,1, - 107,8,114,112,116,4,100,1,107,8,114,76,116,5,124,0, - 131,1,125,1,110,8,116,6,124,0,131,1,125,1,124,0, - 102,1,100,2,100,3,132,1,125,2,116,7,160,8,124,1, - 124,2,161,2,116,2,124,0,60,0,87,0,100,1,116,0, - 160,9,161,0,1,0,88,0,124,1,83,0,41,4,122,139, - 71,101,116,32,111,114,32,99,114,101,97,116,101,32,116,104, - 101,32,109,111,100,117,108,101,32,108,111,99,107,32,102,111, - 114,32,97,32,103,105,118,101,110,32,109,111,100,117,108,101, - 32,110,97,109,101,46,10,10,32,32,32,32,65,99,113,117, - 105,114,101,47,114,101,108,101,97,115,101,32,105,110,116,101, - 114,110,97,108,108,121,32,116,104,101,32,103,108,111,98,97, - 108,32,105,109,112,111,114,116,32,108,111,99,107,32,116,111, - 32,112,114,111,116,101,99,116,10,32,32,32,32,95,109,111, - 100,117,108,101,95,108,111,99,107,115,46,78,99,2,0,0, - 0,0,0,0,0,2,0,0,0,11,0,0,0,83,0,0, - 0,115,48,0,0,0,116,0,160,1,161,0,1,0,122,24, - 116,2,160,3,124,1,161,1,124,0,107,8,114,30,116,2, - 124,1,61,0,87,0,100,0,116,0,160,4,161,0,1,0, - 88,0,100,0,83,0,41,1,78,41,5,218,4,95,105,109, - 112,218,12,97,99,113,117,105,114,101,95,108,111,99,107,218, - 13,95,109,111,100,117,108,101,95,108,111,99,107,115,114,30, - 0,0,0,218,12,114,101,108,101,97,115,101,95,108,111,99, - 107,41,2,218,3,114,101,102,114,15,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,218,2,99,98, - 176,0,0,0,115,10,0,0,0,0,1,8,1,2,4,14, - 1,10,2,122,28,95,103,101,116,95,109,111,100,117,108,101, - 95,108,111,99,107,46,60,108,111,99,97,108,115,62,46,99, - 98,41,10,114,49,0,0,0,114,50,0,0,0,114,51,0, - 0,0,218,8,75,101,121,69,114,114,111,114,114,20,0,0, - 0,114,41,0,0,0,114,18,0,0,0,218,8,95,119,101, - 97,107,114,101,102,114,53,0,0,0,114,52,0,0,0,41, - 3,114,15,0,0,0,114,21,0,0,0,114,54,0,0,0, + 0,0,114,11,0,0,0,114,96,0,0,0,49,1,0,0, + 115,6,0,0,0,8,2,8,4,8,7,114,96,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, + 0,64,0,0,0,115,114,0,0,0,101,0,90,1,100,0, + 90,2,100,1,90,3,100,2,100,2,100,2,100,3,156,3, + 100,4,100,5,132,2,90,4,100,6,100,7,132,0,90,5, + 100,8,100,9,132,0,90,6,101,7,100,10,100,11,132,0, + 131,1,90,8,101,8,106,9,100,12,100,11,132,0,131,1, + 90,8,101,7,100,13,100,14,132,0,131,1,90,10,101,7, + 100,15,100,16,132,0,131,1,90,11,101,11,106,9,100,17, + 100,16,132,0,131,1,90,11,100,2,83,0,41,18,218,10, + 77,111,100,117,108,101,83,112,101,99,97,208,5,0,0,84, + 104,101,32,115,112,101,99,105,102,105,99,97,116,105,111,110, + 32,102,111,114,32,97,32,109,111,100,117,108,101,44,32,117, + 115,101,100,32,102,111,114,32,108,111,97,100,105,110,103,46, + 10,10,32,32,32,32,65,32,109,111,100,117,108,101,39,115, + 32,115,112,101,99,32,105,115,32,116,104,101,32,115,111,117, + 114,99,101,32,102,111,114,32,105,110,102,111,114,109,97,116, + 105,111,110,32,97,98,111,117,116,32,116,104,101,32,109,111, + 100,117,108,101,46,32,32,70,111,114,10,32,32,32,32,100, + 97,116,97,32,97,115,115,111,99,105,97,116,101,100,32,119, + 105,116,104,32,116,104,101,32,109,111,100,117,108,101,44,32, + 105,110,99,108,117,100,105,110,103,32,115,111,117,114,99,101, + 44,32,117,115,101,32,116,104,101,32,115,112,101,99,39,115, + 10,32,32,32,32,108,111,97,100,101,114,46,10,10,32,32, + 32,32,96,110,97,109,101,96,32,105,115,32,116,104,101,32, + 97,98,115,111,108,117,116,101,32,110,97,109,101,32,111,102, + 32,116,104,101,32,109,111,100,117,108,101,46,32,32,96,108, + 111,97,100,101,114,96,32,105,115,32,116,104,101,32,108,111, + 97,100,101,114,10,32,32,32,32,116,111,32,117,115,101,32, + 119,104,101,110,32,108,111,97,100,105,110,103,32,116,104,101, + 32,109,111,100,117,108,101,46,32,32,96,112,97,114,101,110, + 116,96,32,105,115,32,116,104,101,32,110,97,109,101,32,111, + 102,32,116,104,101,10,32,32,32,32,112,97,99,107,97,103, + 101,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, + 105,110,46,32,32,84,104,101,32,112,97,114,101,110,116,32, + 105,115,32,100,101,114,105,118,101,100,32,102,114,111,109,32, + 116,104,101,32,110,97,109,101,46,10,10,32,32,32,32,96, + 105,115,95,112,97,99,107,97,103,101,96,32,100,101,116,101, + 114,109,105,110,101,115,32,105,102,32,116,104,101,32,109,111, + 100,117,108,101,32,105,115,32,99,111,110,115,105,100,101,114, + 101,100,32,97,32,112,97,99,107,97,103,101,32,111,114,10, + 32,32,32,32,110,111,116,46,32,32,79,110,32,109,111,100, + 117,108,101,115,32,116,104,105,115,32,105,115,32,114,101,102, + 108,101,99,116,101,100,32,98,121,32,116,104,101,32,96,95, + 95,112,97,116,104,95,95,96,32,97,116,116,114,105,98,117, + 116,101,46,10,10,32,32,32,32,96,111,114,105,103,105,110, + 96,32,105,115,32,116,104,101,32,115,112,101,99,105,102,105, + 99,32,108,111,99,97,116,105,111,110,32,117,115,101,100,32, + 98,121,32,116,104,101,32,108,111,97,100,101,114,32,102,114, + 111,109,32,119,104,105,99,104,32,116,111,10,32,32,32,32, + 108,111,97,100,32,116,104,101,32,109,111,100,117,108,101,44, + 32,105,102,32,116,104,97,116,32,105,110,102,111,114,109,97, + 116,105,111,110,32,105,115,32,97,118,97,105,108,97,98,108, + 101,46,32,32,87,104,101,110,32,102,105,108,101,110,97,109, + 101,32,105,115,10,32,32,32,32,115,101,116,44,32,111,114, + 105,103,105,110,32,119,105,108,108,32,109,97,116,99,104,46, + 10,10,32,32,32,32,96,104,97,115,95,108,111,99,97,116, + 105,111,110,96,32,105,110,100,105,99,97,116,101,115,32,116, + 104,97,116,32,97,32,115,112,101,99,39,115,32,34,111,114, + 105,103,105,110,34,32,114,101,102,108,101,99,116,115,32,97, + 32,108,111,99,97,116,105,111,110,46,10,32,32,32,32,87, + 104,101,110,32,116,104,105,115,32,105,115,32,84,114,117,101, + 44,32,96,95,95,102,105,108,101,95,95,96,32,97,116,116, + 114,105,98,117,116,101,32,111,102,32,116,104,101,32,109,111, + 100,117,108,101,32,105,115,32,115,101,116,46,10,10,32,32, + 32,32,96,99,97,99,104,101,100,96,32,105,115,32,116,104, + 101,32,108,111,99,97,116,105,111,110,32,111,102,32,116,104, + 101,32,99,97,99,104,101,100,32,98,121,116,101,99,111,100, + 101,32,102,105,108,101,44,32,105,102,32,97,110,121,46,32, + 32,73,116,10,32,32,32,32,99,111,114,114,101,115,112,111, + 110,100,115,32,116,111,32,116,104,101,32,96,95,95,99,97, + 99,104,101,100,95,95,96,32,97,116,116,114,105,98,117,116, + 101,46,10,10,32,32,32,32,96,115,117,98,109,111,100,117, + 108,101,95,115,101,97,114,99,104,95,108,111,99,97,116,105, + 111,110,115,96,32,105,115,32,116,104,101,32,115,101,113,117, + 101,110,99,101,32,111,102,32,112,97,116,104,32,101,110,116, + 114,105,101,115,32,116,111,10,32,32,32,32,115,101,97,114, + 99,104,32,119,104,101,110,32,105,109,112,111,114,116,105,110, + 103,32,115,117,98,109,111,100,117,108,101,115,46,32,32,73, + 102,32,115,101,116,44,32,105,115,95,112,97,99,107,97,103, + 101,32,115,104,111,117,108,100,32,98,101,10,32,32,32,32, + 84,114,117,101,45,45,97,110,100,32,70,97,108,115,101,32, + 111,116,104,101,114,119,105,115,101,46,10,10,32,32,32,32, + 80,97,99,107,97,103,101,115,32,97,114,101,32,115,105,109, + 112,108,121,32,109,111,100,117,108,101,115,32,116,104,97,116, + 32,40,109,97,121,41,32,104,97,118,101,32,115,117,98,109, + 111,100,117,108,101,115,46,32,32,73,102,32,97,32,115,112, + 101,99,10,32,32,32,32,104,97,115,32,97,32,110,111,110, + 45,78,111,110,101,32,118,97,108,117,101,32,105,110,32,96, + 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, + 95,108,111,99,97,116,105,111,110,115,96,44,32,116,104,101, + 32,105,109,112,111,114,116,10,32,32,32,32,115,121,115,116, + 101,109,32,119,105,108,108,32,99,111,110,115,105,100,101,114, + 32,109,111,100,117,108,101,115,32,108,111,97,100,101,100,32, + 102,114,111,109,32,116,104,101,32,115,112,101,99,32,97,115, + 32,112,97,99,107,97,103,101,115,46,10,10,32,32,32,32, + 79,110,108,121,32,102,105,110,100,101,114,115,32,40,115,101, + 101,32,105,109,112,111,114,116,108,105,98,46,97,98,99,46, + 77,101,116,97,80,97,116,104,70,105,110,100,101,114,32,97, + 110,100,10,32,32,32,32,105,109,112,111,114,116,108,105,98, + 46,97,98,99,46,80,97,116,104,69,110,116,114,121,70,105, + 110,100,101,114,41,32,115,104,111,117,108,100,32,109,111,100, + 105,102,121,32,77,111,100,117,108,101,83,112,101,99,32,105, + 110,115,116,97,110,99,101,115,46,10,10,32,32,32,32,78, + 41,3,218,6,111,114,105,103,105,110,218,12,108,111,97,100, + 101,114,95,115,116,97,116,101,218,10,105,115,95,112,97,99, + 107,97,103,101,99,3,0,0,0,3,0,0,0,6,0,0, + 0,2,0,0,0,67,0,0,0,115,54,0,0,0,124,1, + 124,0,95,0,124,2,124,0,95,1,124,3,124,0,95,2, + 124,4,124,0,95,3,124,5,114,32,103,0,110,2,100,0, + 124,0,95,4,100,1,124,0,95,5,100,0,124,0,95,6, + 100,0,83,0,41,2,78,70,41,7,114,15,0,0,0,114, + 93,0,0,0,114,103,0,0,0,114,104,0,0,0,218,26, + 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, + 95,108,111,99,97,116,105,111,110,115,218,13,95,115,101,116, + 95,102,105,108,101,97,116,116,114,218,7,95,99,97,99,104, + 101,100,41,6,114,26,0,0,0,114,15,0,0,0,114,93, + 0,0,0,114,103,0,0,0,114,104,0,0,0,114,105,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,27,0,0,0,113,1,0,0,115,14,0,0,0,0, + 2,6,1,6,1,6,1,6,1,14,3,6,1,122,19,77, + 111,100,117,108,101,83,112,101,99,46,95,95,105,110,105,116, + 95,95,99,1,0,0,0,0,0,0,0,2,0,0,0,6, + 0,0,0,67,0,0,0,115,102,0,0,0,100,1,160,0, + 124,0,106,1,161,1,100,2,160,0,124,0,106,2,161,1, + 103,2,125,1,124,0,106,3,100,0,107,9,114,52,124,1, + 160,4,100,3,160,0,124,0,106,3,161,1,161,1,1,0, + 124,0,106,5,100,0,107,9,114,80,124,1,160,4,100,4, + 160,0,124,0,106,5,161,1,161,1,1,0,100,5,160,0, + 124,0,106,6,106,7,100,6,160,8,124,1,161,1,161,2, + 83,0,41,7,78,122,9,110,97,109,101,61,123,33,114,125, + 122,11,108,111,97,100,101,114,61,123,33,114,125,122,11,111, + 114,105,103,105,110,61,123,33,114,125,122,29,115,117,98,109, + 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, + 97,116,105,111,110,115,61,123,125,122,6,123,125,40,123,125, + 41,122,2,44,32,41,9,114,38,0,0,0,114,15,0,0, + 0,114,93,0,0,0,114,103,0,0,0,218,6,97,112,112, + 101,110,100,114,106,0,0,0,218,9,95,95,99,108,97,115, + 115,95,95,114,1,0,0,0,218,4,106,111,105,110,41,2, + 114,26,0,0,0,114,47,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,40,0,0,0,125,1, + 0,0,115,16,0,0,0,0,1,10,1,14,1,10,1,18, + 1,10,1,8,1,10,1,122,19,77,111,100,117,108,101,83, + 112,101,99,46,95,95,114,101,112,114,95,95,99,2,0,0, + 0,0,0,0,0,3,0,0,0,11,0,0,0,67,0,0, + 0,115,102,0,0,0,124,0,106,0,125,2,121,70,124,0, + 106,1,124,1,106,1,107,2,111,76,124,0,106,2,124,1, + 106,2,107,2,111,76,124,0,106,3,124,1,106,3,107,2, + 111,76,124,2,124,1,106,0,107,2,111,76,124,0,106,4, + 124,1,106,4,107,2,111,76,124,0,106,5,124,1,106,5, + 107,2,83,0,4,0,116,6,107,10,114,96,1,0,1,0, + 1,0,100,1,83,0,88,0,100,0,83,0,41,2,78,70, + 41,7,114,106,0,0,0,114,15,0,0,0,114,93,0,0, + 0,114,103,0,0,0,218,6,99,97,99,104,101,100,218,12, + 104,97,115,95,108,111,99,97,116,105,111,110,114,90,0,0, + 0,41,3,114,26,0,0,0,90,5,111,116,104,101,114,90, + 4,115,109,115,108,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,6,95,95,101,113,95,95,135,1,0,0, + 115,20,0,0,0,0,1,6,1,2,1,12,1,12,1,12, + 1,10,1,12,1,12,1,14,1,122,17,77,111,100,117,108, + 101,83,112,101,99,46,95,95,101,113,95,95,99,1,0,0, + 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, + 0,115,58,0,0,0,124,0,106,0,100,0,107,8,114,52, + 124,0,106,1,100,0,107,9,114,52,124,0,106,2,114,52, + 116,3,100,0,107,8,114,38,116,4,130,1,116,3,160,5, + 124,0,106,1,161,1,124,0,95,0,124,0,106,0,83,0, + 41,1,78,41,6,114,108,0,0,0,114,103,0,0,0,114, + 107,0,0,0,218,19,95,98,111,111,116,115,116,114,97,112, + 95,101,120,116,101,114,110,97,108,218,19,78,111,116,73,109, + 112,108,101,109,101,110,116,101,100,69,114,114,111,114,90,11, + 95,103,101,116,95,99,97,99,104,101,100,41,1,114,26,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,112,0,0,0,147,1,0,0,115,12,0,0,0,0, + 2,10,1,16,1,8,1,4,1,14,1,122,17,77,111,100, + 117,108,101,83,112,101,99,46,99,97,99,104,101,100,99,2, + 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, + 0,0,0,115,10,0,0,0,124,1,124,0,95,0,100,0, + 83,0,41,1,78,41,1,114,108,0,0,0,41,2,114,26, + 0,0,0,114,112,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,112,0,0,0,156,1,0,0, + 115,2,0,0,0,0,2,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,36,0,0, + 0,124,0,106,0,100,1,107,8,114,26,124,0,106,1,160, + 2,100,2,161,1,100,3,25,0,83,0,124,0,106,1,83, + 0,100,1,83,0,41,4,122,32,84,104,101,32,110,97,109, + 101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,39, + 115,32,112,97,114,101,110,116,46,78,218,1,46,114,19,0, + 0,0,41,3,114,106,0,0,0,114,15,0,0,0,218,10, + 114,112,97,114,116,105,116,105,111,110,41,1,114,26,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,6,112,97,114,101,110,116,160,1,0,0,115,6,0,0, + 0,0,3,10,1,16,2,122,17,77,111,100,117,108,101,83, + 112,101,99,46,112,97,114,101,110,116,99,1,0,0,0,0, + 0,0,0,1,0,0,0,1,0,0,0,67,0,0,0,115, + 6,0,0,0,124,0,106,0,83,0,41,1,78,41,1,114, + 107,0,0,0,41,1,114,26,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,113,0,0,0,168, + 1,0,0,115,2,0,0,0,0,2,122,23,77,111,100,117, + 108,101,83,112,101,99,46,104,97,115,95,108,111,99,97,116, + 105,111,110,99,2,0,0,0,0,0,0,0,2,0,0,0, + 2,0,0,0,67,0,0,0,115,14,0,0,0,116,0,124, + 1,131,1,124,0,95,1,100,0,83,0,41,1,78,41,2, + 218,4,98,111,111,108,114,107,0,0,0,41,2,114,26,0, + 0,0,218,5,118,97,108,117,101,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,113,0,0,0,172,1,0, + 0,115,2,0,0,0,0,2,41,12,114,1,0,0,0,114, + 0,0,0,0,114,2,0,0,0,114,3,0,0,0,114,27, + 0,0,0,114,40,0,0,0,114,114,0,0,0,218,8,112, + 114,111,112,101,114,116,121,114,112,0,0,0,218,6,115,101, + 116,116,101,114,114,119,0,0,0,114,113,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,102,0,0,0,76,1,0,0,115,18,0,0,0, + 12,37,4,1,14,11,8,10,8,12,12,9,14,4,12,8, + 12,4,114,102,0,0,0,41,2,114,103,0,0,0,114,105, + 0,0,0,99,2,0,0,0,2,0,0,0,6,0,0,0, + 14,0,0,0,67,0,0,0,115,154,0,0,0,116,0,124, + 1,100,1,131,2,114,74,116,1,100,2,107,8,114,22,116, + 2,130,1,116,1,106,3,125,4,124,3,100,2,107,8,114, + 48,124,4,124,0,124,1,100,3,141,2,83,0,124,3,114, + 56,103,0,110,2,100,2,125,5,124,4,124,0,124,1,124, + 5,100,4,141,3,83,0,124,3,100,2,107,8,114,138,116, + 0,124,1,100,5,131,2,114,134,121,14,124,1,160,4,124, + 0,161,1,125,3,87,0,113,138,4,0,116,5,107,10,114, + 130,1,0,1,0,1,0,100,2,125,3,89,0,113,138,88, + 0,110,4,100,6,125,3,116,6,124,0,124,1,124,2,124, + 3,100,7,141,4,83,0,41,8,122,53,82,101,116,117,114, + 110,32,97,32,109,111,100,117,108,101,32,115,112,101,99,32, + 98,97,115,101,100,32,111,110,32,118,97,114,105,111,117,115, + 32,108,111,97,100,101,114,32,109,101,116,104,111,100,115,46, + 90,12,103,101,116,95,102,105,108,101,110,97,109,101,78,41, + 1,114,93,0,0,0,41,2,114,93,0,0,0,114,106,0, + 0,0,114,105,0,0,0,70,41,2,114,103,0,0,0,114, + 105,0,0,0,41,7,114,4,0,0,0,114,115,0,0,0, + 114,116,0,0,0,218,23,115,112,101,99,95,102,114,111,109, + 95,102,105,108,101,95,108,111,99,97,116,105,111,110,114,105, + 0,0,0,114,70,0,0,0,114,102,0,0,0,41,6,114, + 15,0,0,0,114,93,0,0,0,114,103,0,0,0,114,105, + 0,0,0,114,124,0,0,0,90,6,115,101,97,114,99,104, 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 45,0,0,0,157,0,0,0,115,28,0,0,0,0,6,8, - 1,2,1,2,1,14,1,14,1,10,2,8,1,8,1,10, - 2,8,2,12,11,20,2,10,2,114,45,0,0,0,99,1, - 0,0,0,0,0,0,0,2,0,0,0,11,0,0,0,67, - 0,0,0,115,54,0,0,0,116,0,124,0,131,1,125,1, - 121,12,124,1,160,1,161,0,1,0,87,0,110,20,4,0, - 116,2,107,10,114,40,1,0,1,0,1,0,89,0,110,10, - 88,0,124,1,160,3,161,0,1,0,100,1,83,0,41,2, - 122,189,65,99,113,117,105,114,101,115,32,116,104,101,110,32, - 114,101,108,101,97,115,101,115,32,116,104,101,32,109,111,100, - 117,108,101,32,108,111,99,107,32,102,111,114,32,97,32,103, - 105,118,101,110,32,109,111,100,117,108,101,32,110,97,109,101, - 46,10,10,32,32,32,32,84,104,105,115,32,105,115,32,117, - 115,101,100,32,116,111,32,101,110,115,117,114,101,32,97,32, - 109,111,100,117,108,101,32,105,115,32,99,111,109,112,108,101, - 116,101,108,121,32,105,110,105,116,105,97,108,105,122,101,100, - 44,32,105,110,32,116,104,101,10,32,32,32,32,101,118,101, - 110,116,32,105,116,32,105,115,32,98,101,105,110,103,32,105, - 109,112,111,114,116,101,100,32,98,121,32,97,110,111,116,104, - 101,114,32,116,104,114,101,97,100,46,10,32,32,32,32,78, - 41,4,114,45,0,0,0,114,34,0,0,0,114,17,0,0, - 0,114,35,0,0,0,41,2,114,15,0,0,0,114,21,0, + 78,0,0,0,177,1,0,0,115,34,0,0,0,0,2,10, + 1,8,1,4,1,6,2,8,1,12,1,12,1,6,1,8, + 2,8,1,10,1,2,1,14,1,14,1,12,3,4,2,114, + 78,0,0,0,99,3,0,0,0,0,0,0,0,8,0,0, + 0,53,0,0,0,67,0,0,0,115,56,1,0,0,121,10, + 124,0,106,0,125,3,87,0,110,20,4,0,116,1,107,10, + 114,30,1,0,1,0,1,0,89,0,110,14,88,0,124,3, + 100,0,107,9,114,44,124,3,83,0,124,0,106,2,125,4, + 124,1,100,0,107,8,114,90,121,10,124,0,106,3,125,1, + 87,0,110,20,4,0,116,1,107,10,114,88,1,0,1,0, + 1,0,89,0,110,2,88,0,121,10,124,0,106,4,125,5, + 87,0,110,24,4,0,116,1,107,10,114,124,1,0,1,0, + 1,0,100,0,125,5,89,0,110,2,88,0,124,2,100,0, + 107,8,114,184,124,5,100,0,107,8,114,180,121,10,124,1, + 106,5,125,2,87,0,113,184,4,0,116,1,107,10,114,176, + 1,0,1,0,1,0,100,0,125,2,89,0,113,184,88,0, + 110,4,124,5,125,2,121,10,124,0,106,6,125,6,87,0, + 110,24,4,0,116,1,107,10,114,218,1,0,1,0,1,0, + 100,0,125,6,89,0,110,2,88,0,121,14,116,7,124,0, + 106,8,131,1,125,7,87,0,110,26,4,0,116,1,107,10, + 144,1,114,4,1,0,1,0,1,0,100,0,125,7,89,0, + 110,2,88,0,116,9,124,4,124,1,124,2,100,1,141,3, + 125,3,124,5,100,0,107,8,144,1,114,34,100,2,110,2, + 100,3,124,3,95,10,124,6,124,3,95,11,124,7,124,3, + 95,12,124,3,83,0,41,4,78,41,1,114,103,0,0,0, + 70,84,41,13,114,89,0,0,0,114,90,0,0,0,114,1, + 0,0,0,114,85,0,0,0,114,92,0,0,0,90,7,95, + 79,82,73,71,73,78,218,10,95,95,99,97,99,104,101,100, + 95,95,218,4,108,105,115,116,218,8,95,95,112,97,116,104, + 95,95,114,102,0,0,0,114,107,0,0,0,114,112,0,0, + 0,114,106,0,0,0,41,8,114,83,0,0,0,114,93,0, + 0,0,114,103,0,0,0,114,82,0,0,0,114,15,0,0, + 0,90,8,108,111,99,97,116,105,111,110,114,112,0,0,0, + 114,106,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,17,95,115,112,101,99,95,102,114,111,109, + 95,109,111,100,117,108,101,203,1,0,0,115,72,0,0,0, + 0,2,2,1,10,1,14,1,6,2,8,1,4,2,6,1, + 8,1,2,1,10,1,14,2,6,1,2,1,10,1,14,1, + 10,1,8,1,8,1,2,1,10,1,14,1,12,2,4,1, + 2,1,10,1,14,1,10,1,2,1,14,1,16,1,10,2, + 14,1,20,1,6,1,6,1,114,128,0,0,0,70,41,1, + 218,8,111,118,101,114,114,105,100,101,99,2,0,0,0,1, + 0,0,0,5,0,0,0,59,0,0,0,67,0,0,0,115, + 212,1,0,0,124,2,115,20,116,0,124,1,100,1,100,0, + 131,3,100,0,107,8,114,54,121,12,124,0,106,1,124,1, + 95,2,87,0,110,20,4,0,116,3,107,10,114,52,1,0, + 1,0,1,0,89,0,110,2,88,0,124,2,115,74,116,0, + 124,1,100,2,100,0,131,3,100,0,107,8,114,166,124,0, + 106,4,125,3,124,3,100,0,107,8,114,134,124,0,106,5, + 100,0,107,9,114,134,116,6,100,0,107,8,114,110,116,7, + 130,1,116,6,106,8,125,4,124,4,160,9,124,4,161,1, + 125,3,124,0,106,5,124,3,95,10,121,10,124,3,124,1, + 95,11,87,0,110,20,4,0,116,3,107,10,114,164,1,0, + 1,0,1,0,89,0,110,2,88,0,124,2,115,186,116,0, + 124,1,100,3,100,0,131,3,100,0,107,8,114,220,121,12, + 124,0,106,12,124,1,95,13,87,0,110,20,4,0,116,3, + 107,10,114,218,1,0,1,0,1,0,89,0,110,2,88,0, + 121,10,124,0,124,1,95,14,87,0,110,20,4,0,116,3, + 107,10,114,250,1,0,1,0,1,0,89,0,110,2,88,0, + 124,2,144,1,115,20,116,0,124,1,100,4,100,0,131,3, + 100,0,107,8,144,1,114,68,124,0,106,5,100,0,107,9, + 144,1,114,68,121,12,124,0,106,5,124,1,95,15,87,0, + 110,22,4,0,116,3,107,10,144,1,114,66,1,0,1,0, + 1,0,89,0,110,2,88,0,124,0,106,16,144,1,114,208, + 124,2,144,1,115,100,116,0,124,1,100,5,100,0,131,3, + 100,0,107,8,144,1,114,136,121,12,124,0,106,17,124,1, + 95,18,87,0,110,22,4,0,116,3,107,10,144,1,114,134, + 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, + 115,160,116,0,124,1,100,6,100,0,131,3,100,0,107,8, + 144,1,114,208,124,0,106,19,100,0,107,9,144,1,114,208, + 121,12,124,0,106,19,124,1,95,20,87,0,110,22,4,0, + 116,3,107,10,144,1,114,206,1,0,1,0,1,0,89,0, + 110,2,88,0,124,1,83,0,41,7,78,114,1,0,0,0, + 114,85,0,0,0,218,11,95,95,112,97,99,107,97,103,101, + 95,95,114,127,0,0,0,114,92,0,0,0,114,125,0,0, + 0,41,21,114,6,0,0,0,114,15,0,0,0,114,1,0, + 0,0,114,90,0,0,0,114,93,0,0,0,114,106,0,0, + 0,114,115,0,0,0,114,116,0,0,0,218,16,95,78,97, + 109,101,115,112,97,99,101,76,111,97,100,101,114,218,7,95, + 95,110,101,119,95,95,90,5,95,112,97,116,104,114,85,0, + 0,0,114,119,0,0,0,114,130,0,0,0,114,89,0,0, + 0,114,127,0,0,0,114,113,0,0,0,114,103,0,0,0, + 114,92,0,0,0,114,112,0,0,0,114,125,0,0,0,41, + 5,114,82,0,0,0,114,83,0,0,0,114,129,0,0,0, + 114,93,0,0,0,114,131,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,218,18,95,105,110,105,116, + 95,109,111,100,117,108,101,95,97,116,116,114,115,248,1,0, + 0,115,92,0,0,0,0,4,20,1,2,1,12,1,14,1, + 6,2,20,1,6,1,8,2,10,1,8,1,4,1,6,2, + 10,1,8,1,2,1,10,1,14,1,6,2,20,1,2,1, + 12,1,14,1,6,2,2,1,10,1,14,1,6,2,24,1, + 12,1,2,1,12,1,16,1,6,2,8,1,24,1,2,1, + 12,1,16,1,6,2,24,1,12,1,2,1,12,1,16,1, + 6,1,114,133,0,0,0,99,1,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,67,0,0,0,115,82,0,0, + 0,100,1,125,1,116,0,124,0,106,1,100,2,131,2,114, + 30,124,0,106,1,160,2,124,0,161,1,125,1,110,20,116, + 0,124,0,106,1,100,3,131,2,114,50,116,3,100,4,131, + 1,130,1,124,1,100,1,107,8,114,68,116,4,124,0,106, + 5,131,1,125,1,116,6,124,0,124,1,131,2,1,0,124, + 1,83,0,41,5,122,43,67,114,101,97,116,101,32,97,32, + 109,111,100,117,108,101,32,98,97,115,101,100,32,111,110,32, + 116,104,101,32,112,114,111,118,105,100,101,100,32,115,112,101, + 99,46,78,218,13,99,114,101,97,116,101,95,109,111,100,117, + 108,101,218,11,101,120,101,99,95,109,111,100,117,108,101,122, + 66,108,111,97,100,101,114,115,32,116,104,97,116,32,100,101, + 102,105,110,101,32,101,120,101,99,95,109,111,100,117,108,101, + 40,41,32,109,117,115,116,32,97,108,115,111,32,100,101,102, + 105,110,101,32,99,114,101,97,116,101,95,109,111,100,117,108, + 101,40,41,41,7,114,4,0,0,0,114,93,0,0,0,114, + 134,0,0,0,114,70,0,0,0,114,16,0,0,0,114,15, + 0,0,0,114,133,0,0,0,41,2,114,82,0,0,0,114, + 83,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,16,109,111,100,117,108,101,95,102,114,111,109, + 95,115,112,101,99,52,2,0,0,115,18,0,0,0,0,3, + 4,1,12,3,14,1,12,1,8,2,8,1,10,1,10,1, + 114,136,0,0,0,99,1,0,0,0,0,0,0,0,2,0, + 0,0,4,0,0,0,67,0,0,0,115,106,0,0,0,124, + 0,106,0,100,1,107,8,114,14,100,2,110,4,124,0,106, + 0,125,1,124,0,106,1,100,1,107,8,114,66,124,0,106, + 2,100,1,107,8,114,50,100,3,160,3,124,1,161,1,83, + 0,100,4,160,3,124,1,124,0,106,2,161,2,83,0,110, + 36,124,0,106,4,114,86,100,5,160,3,124,1,124,0,106, + 1,161,2,83,0,100,6,160,3,124,0,106,0,124,0,106, + 1,161,2,83,0,100,1,83,0,41,7,122,38,82,101,116, + 117,114,110,32,116,104,101,32,114,101,112,114,32,116,111,32, + 117,115,101,32,102,111,114,32,116,104,101,32,109,111,100,117, + 108,101,46,78,114,87,0,0,0,122,13,60,109,111,100,117, + 108,101,32,123,33,114,125,62,122,20,60,109,111,100,117,108, + 101,32,123,33,114,125,32,40,123,33,114,125,41,62,122,23, + 60,109,111,100,117,108,101,32,123,33,114,125,32,102,114,111, + 109,32,123,33,114,125,62,122,18,60,109,111,100,117,108,101, + 32,123,33,114,125,32,40,123,125,41,62,41,5,114,15,0, + 0,0,114,103,0,0,0,114,93,0,0,0,114,38,0,0, + 0,114,113,0,0,0,41,2,114,82,0,0,0,114,15,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,19,95,108,111,99,107,95,117,110,108,111,99,107,95, - 109,111,100,117,108,101,194,0,0,0,115,12,0,0,0,0, - 6,8,1,2,1,12,1,14,3,6,2,114,57,0,0,0, - 99,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0, - 0,79,0,0,0,115,10,0,0,0,124,0,124,1,124,2, - 142,1,83,0,41,1,97,46,1,0,0,114,101,109,111,118, - 101,95,105,109,112,111,114,116,108,105,98,95,102,114,97,109, - 101,115,32,105,110,32,105,109,112,111,114,116,46,99,32,119, - 105,108,108,32,97,108,119,97,121,115,32,114,101,109,111,118, - 101,32,115,101,113,117,101,110,99,101,115,10,32,32,32,32, - 111,102,32,105,109,112,111,114,116,108,105,98,32,102,114,97, - 109,101,115,32,116,104,97,116,32,101,110,100,32,119,105,116, - 104,32,97,32,99,97,108,108,32,116,111,32,116,104,105,115, - 32,102,117,110,99,116,105,111,110,10,10,32,32,32,32,85, - 115,101,32,105,116,32,105,110,115,116,101,97,100,32,111,102, - 32,97,32,110,111,114,109,97,108,32,99,97,108,108,32,105, - 110,32,112,108,97,99,101,115,32,119,104,101,114,101,32,105, - 110,99,108,117,100,105,110,103,32,116,104,101,32,105,109,112, - 111,114,116,108,105,98,10,32,32,32,32,102,114,97,109,101, - 115,32,105,110,116,114,111,100,117,99,101,115,32,117,110,119, - 97,110,116,101,100,32,110,111,105,115,101,32,105,110,116,111, - 32,116,104,101,32,116,114,97,99,101,98,97,99,107,32,40, - 101,46,103,46,32,119,104,101,110,32,101,120,101,99,117,116, - 105,110,103,10,32,32,32,32,109,111,100,117,108,101,32,99, - 111,100,101,41,10,32,32,32,32,114,10,0,0,0,41,3, - 218,1,102,114,47,0,0,0,90,4,107,119,100,115,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,218,25,95, - 99,97,108,108,95,119,105,116,104,95,102,114,97,109,101,115, - 95,114,101,109,111,118,101,100,211,0,0,0,115,2,0,0, - 0,0,8,114,59,0,0,0,114,33,0,0,0,41,1,218, - 9,118,101,114,98,111,115,105,116,121,99,1,0,0,0,1, - 0,0,0,3,0,0,0,4,0,0,0,71,0,0,0,115, - 54,0,0,0,116,0,106,1,106,2,124,1,107,5,114,50, - 124,0,160,3,100,6,161,1,115,30,100,3,124,0,23,0, - 125,0,116,4,124,0,106,5,124,2,142,0,116,0,106,6, - 100,4,141,2,1,0,100,5,83,0,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,41,1,90,4,102, - 105,108,101,78,41,2,114,61,0,0,0,114,62,0,0,0, - 41,7,114,14,0,0,0,218,5,102,108,97,103,115,218,7, - 118,101,114,98,111,115,101,218,10,115,116,97,114,116,115,119, - 105,116,104,218,5,112,114,105,110,116,114,38,0,0,0,218, - 6,115,116,100,101,114,114,41,3,218,7,109,101,115,115,97, - 103,101,114,60,0,0,0,114,47,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,218,16,95,118,101, - 114,98,111,115,101,95,109,101,115,115,97,103,101,222,0,0, - 0,115,8,0,0,0,0,2,12,1,10,1,8,1,114,69, - 0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,3,0,0,0,115,26,0,0,0,135,0,102, - 1,100,1,100,2,132,8,125,1,116,0,124,1,136,0,131, - 2,1,0,124,1,83,0,41,3,122,49,68,101,99,111,114, - 97,116,111,114,32,116,111,32,118,101,114,105,102,121,32,116, - 104,101,32,110,97,109,101,100,32,109,111,100,117,108,101,32, - 105,115,32,98,117,105,108,116,45,105,110,46,99,2,0,0, - 0,0,0,0,0,2,0,0,0,4,0,0,0,19,0,0, - 0,115,38,0,0,0,124,1,116,0,106,1,107,7,114,28, - 116,2,100,1,160,3,124,1,161,1,124,1,100,2,141,2, - 130,1,136,0,124,0,124,1,131,2,83,0,41,3,78,122, - 29,123,33,114,125,32,105,115,32,110,111,116,32,97,32,98, - 117,105,108,116,45,105,110,32,109,111,100,117,108,101,41,1, - 114,15,0,0,0,41,4,114,14,0,0,0,218,20,98,117, - 105,108,116,105,110,95,109,111,100,117,108,101,95,110,97,109, - 101,115,218,11,73,109,112,111,114,116,69,114,114,111,114,114, - 38,0,0,0,41,2,114,26,0,0,0,218,8,102,117,108, - 108,110,97,109,101,41,1,218,3,102,120,110,114,10,0,0, - 0,114,11,0,0,0,218,25,95,114,101,113,117,105,114,101, - 115,95,98,117,105,108,116,105,110,95,119,114,97,112,112,101, - 114,232,0,0,0,115,8,0,0,0,0,1,10,1,10,1, - 8,1,122,52,95,114,101,113,117,105,114,101,115,95,98,117, - 105,108,116,105,110,46,60,108,111,99,97,108,115,62,46,95, - 114,101,113,117,105,114,101,115,95,98,117,105,108,116,105,110, - 95,119,114,97,112,112,101,114,41,1,114,12,0,0,0,41, - 2,114,73,0,0,0,114,74,0,0,0,114,10,0,0,0, - 41,1,114,73,0,0,0,114,11,0,0,0,218,17,95,114, - 101,113,117,105,114,101,115,95,98,117,105,108,116,105,110,230, - 0,0,0,115,6,0,0,0,0,2,12,5,10,1,114,75, - 0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,3,0,0,0,115,26,0,0,0,135,0,102, - 1,100,1,100,2,132,8,125,1,116,0,124,1,136,0,131, - 2,1,0,124,1,83,0,41,3,122,47,68,101,99,111,114, - 97,116,111,114,32,116,111,32,118,101,114,105,102,121,32,116, - 104,101,32,110,97,109,101,100,32,109,111,100,117,108,101,32, - 105,115,32,102,114,111,122,101,110,46,99,2,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, - 38,0,0,0,116,0,160,1,124,1,161,1,115,28,116,2, - 100,1,160,3,124,1,161,1,124,1,100,2,141,2,130,1, - 136,0,124,0,124,1,131,2,83,0,41,3,78,122,27,123, - 33,114,125,32,105,115,32,110,111,116,32,97,32,102,114,111, - 122,101,110,32,109,111,100,117,108,101,41,1,114,15,0,0, - 0,41,4,114,49,0,0,0,218,9,105,115,95,102,114,111, - 122,101,110,114,71,0,0,0,114,38,0,0,0,41,2,114, - 26,0,0,0,114,72,0,0,0,41,1,114,73,0,0,0, - 114,10,0,0,0,114,11,0,0,0,218,24,95,114,101,113, - 117,105,114,101,115,95,102,114,111,122,101,110,95,119,114,97, - 112,112,101,114,243,0,0,0,115,8,0,0,0,0,1,10, - 1,10,1,8,1,122,50,95,114,101,113,117,105,114,101,115, - 95,102,114,111,122,101,110,46,60,108,111,99,97,108,115,62, - 46,95,114,101,113,117,105,114,101,115,95,102,114,111,122,101, - 110,95,119,114,97,112,112,101,114,41,1,114,12,0,0,0, - 41,2,114,73,0,0,0,114,77,0,0,0,114,10,0,0, - 0,41,1,114,73,0,0,0,114,11,0,0,0,218,16,95, - 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,241, - 0,0,0,115,6,0,0,0,0,2,12,5,10,1,114,78, - 0,0,0,99,2,0,0,0,0,0,0,0,4,0,0,0, - 3,0,0,0,67,0,0,0,115,62,0,0,0,116,0,124, - 1,124,0,131,2,125,2,124,1,116,1,106,2,107,6,114, - 50,116,1,106,2,124,1,25,0,125,3,116,3,124,2,124, - 3,131,2,1,0,116,1,106,2,124,1,25,0,83,0,116, - 4,124,2,131,1,83,0,100,1,83,0,41,2,122,128,76, - 111,97,100,32,116,104,101,32,115,112,101,99,105,102,105,101, - 100,32,109,111,100,117,108,101,32,105,110,116,111,32,115,121, - 115,46,109,111,100,117,108,101,115,32,97,110,100,32,114,101, - 116,117,114,110,32,105,116,46,10,10,32,32,32,32,84,104, - 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,46,32,32,85,115,101,32,108,111, - 97,100,101,114,46,101,120,101,99,95,109,111,100,117,108,101, - 32,105,110,115,116,101,97,100,46,10,10,32,32,32,32,78, - 41,5,218,16,115,112,101,99,95,102,114,111,109,95,108,111, - 97,100,101,114,114,14,0,0,0,218,7,109,111,100,117,108, - 101,115,218,5,95,101,120,101,99,218,5,95,108,111,97,100, - 41,4,114,26,0,0,0,114,72,0,0,0,218,4,115,112, - 101,99,218,6,109,111,100,117,108,101,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,17,95,108,111,97,100, - 95,109,111,100,117,108,101,95,115,104,105,109,253,0,0,0, - 115,12,0,0,0,0,6,10,1,10,1,10,1,10,1,10, - 2,114,85,0,0,0,99,1,0,0,0,0,0,0,0,5, - 0,0,0,36,0,0,0,67,0,0,0,115,216,0,0,0, - 116,0,124,0,100,1,100,0,131,3,125,1,116,1,124,1, - 100,2,131,2,114,54,121,10,124,1,160,2,124,0,161,1, - 83,0,4,0,116,3,107,10,114,52,1,0,1,0,1,0, - 89,0,110,2,88,0,121,10,124,0,106,4,125,2,87,0, - 110,20,4,0,116,5,107,10,114,84,1,0,1,0,1,0, - 89,0,110,18,88,0,124,2,100,0,107,9,114,102,116,6, - 124,2,131,1,83,0,121,10,124,0,106,7,125,3,87,0, - 110,24,4,0,116,5,107,10,114,136,1,0,1,0,1,0, - 100,3,125,3,89,0,110,2,88,0,121,10,124,0,106,8, - 125,4,87,0,110,50,4,0,116,5,107,10,114,198,1,0, - 1,0,1,0,124,1,100,0,107,8,114,182,100,4,160,9, - 124,3,161,1,83,0,100,5,160,9,124,3,124,1,161,2, - 83,0,89,0,110,14,88,0,100,6,160,9,124,3,124,4, - 161,2,83,0,100,0,83,0,41,7,78,218,10,95,95,108, - 111,97,100,101,114,95,95,218,11,109,111,100,117,108,101,95, - 114,101,112,114,250,1,63,122,13,60,109,111,100,117,108,101, - 32,123,33,114,125,62,122,20,60,109,111,100,117,108,101,32, - 123,33,114,125,32,40,123,33,114,125,41,62,122,23,60,109, - 111,100,117,108,101,32,123,33,114,125,32,102,114,111,109,32, - 123,33,114,125,62,41,10,114,6,0,0,0,114,4,0,0, - 0,114,87,0,0,0,218,9,69,120,99,101,112,116,105,111, - 110,218,8,95,95,115,112,101,99,95,95,218,14,65,116,116, - 114,105,98,117,116,101,69,114,114,111,114,218,22,95,109,111, - 100,117,108,101,95,114,101,112,114,95,102,114,111,109,95,115, - 112,101,99,114,1,0,0,0,218,8,95,95,102,105,108,101, - 95,95,114,38,0,0,0,41,5,114,84,0,0,0,218,6, - 108,111,97,100,101,114,114,83,0,0,0,114,15,0,0,0, - 218,8,102,105,108,101,110,97,109,101,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,12,95,109,111,100,117, - 108,101,95,114,101,112,114,13,1,0,0,115,46,0,0,0, - 0,2,12,1,10,4,2,1,10,1,14,1,6,1,2,1, - 10,1,14,1,6,2,8,1,8,4,2,1,10,1,14,1, - 10,1,2,1,10,1,14,1,8,1,10,2,18,2,114,96, - 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,64,0,0,0,115,36,0,0,0,101,0,90, - 1,100,0,90,2,100,1,100,2,132,0,90,3,100,3,100, - 4,132,0,90,4,100,5,100,6,132,0,90,5,100,7,83, - 0,41,8,218,17,95,105,110,115,116,97,108,108,101,100,95, - 115,97,102,101,108,121,99,2,0,0,0,0,0,0,0,2, - 0,0,0,2,0,0,0,67,0,0,0,115,18,0,0,0, - 124,1,124,0,95,0,124,1,106,1,124,0,95,2,100,0, - 83,0,41,1,78,41,3,218,7,95,109,111,100,117,108,101, - 114,90,0,0,0,218,5,95,115,112,101,99,41,2,114,26, - 0,0,0,114,84,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,27,0,0,0,51,1,0,0, - 115,4,0,0,0,0,1,6,1,122,26,95,105,110,115,116, - 97,108,108,101,100,95,115,97,102,101,108,121,46,95,95,105, - 110,105,116,95,95,99,1,0,0,0,0,0,0,0,1,0, - 0,0,3,0,0,0,67,0,0,0,115,28,0,0,0,100, - 1,124,0,106,0,95,1,124,0,106,2,116,3,106,4,124, - 0,106,0,106,5,60,0,100,0,83,0,41,2,78,84,41, - 6,114,99,0,0,0,218,13,95,105,110,105,116,105,97,108, - 105,122,105,110,103,114,98,0,0,0,114,14,0,0,0,114, - 80,0,0,0,114,15,0,0,0,41,1,114,26,0,0,0, + 0,114,91,0,0,0,69,2,0,0,115,16,0,0,0,0, + 3,20,1,10,1,10,1,10,2,16,2,6,1,14,2,114, + 91,0,0,0,99,2,0,0,0,0,0,0,0,4,0,0, + 0,12,0,0,0,67,0,0,0,115,178,0,0,0,124,0, + 106,0,125,2,116,1,124,2,131,1,143,148,1,0,116,2, + 106,3,160,4,124,2,161,1,124,1,107,9,114,54,100,1, + 160,5,124,2,161,1,125,3,116,6,124,3,124,2,100,2, + 141,2,130,1,124,0,106,7,100,3,107,8,114,106,124,0, + 106,8,100,3,107,8,114,88,116,6,100,4,124,0,106,0, + 100,2,141,2,130,1,116,9,124,0,124,1,100,5,100,6, + 141,3,1,0,124,1,83,0,116,9,124,0,124,1,100,5, + 100,6,141,3,1,0,116,10,124,0,106,7,100,7,131,2, + 115,146,124,0,106,7,160,11,124,2,161,1,1,0,110,12, + 124,0,106,7,160,12,124,1,161,1,1,0,87,0,100,3, + 81,0,82,0,88,0,116,2,106,3,124,2,25,0,83,0, + 41,8,122,70,69,120,101,99,117,116,101,32,116,104,101,32, + 115,112,101,99,39,115,32,115,112,101,99,105,102,105,101,100, + 32,109,111,100,117,108,101,32,105,110,32,97,110,32,101,120, + 105,115,116,105,110,103,32,109,111,100,117,108,101,39,115,32, + 110,97,109,101,115,112,97,99,101,46,122,30,109,111,100,117, + 108,101,32,123,33,114,125,32,110,111,116,32,105,110,32,115, + 121,115,46,109,111,100,117,108,101,115,41,1,114,15,0,0, + 0,78,122,14,109,105,115,115,105,110,103,32,108,111,97,100, + 101,114,84,41,1,114,129,0,0,0,114,135,0,0,0,41, + 13,114,15,0,0,0,114,42,0,0,0,114,14,0,0,0, + 114,79,0,0,0,114,30,0,0,0,114,38,0,0,0,114, + 70,0,0,0,114,93,0,0,0,114,106,0,0,0,114,133, + 0,0,0,114,4,0,0,0,218,11,108,111,97,100,95,109, + 111,100,117,108,101,114,135,0,0,0,41,4,114,82,0,0, + 0,114,83,0,0,0,114,15,0,0,0,218,3,109,115,103, 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 46,0,0,0,55,1,0,0,115,4,0,0,0,0,4,8, - 1,122,27,95,105,110,115,116,97,108,108,101,100,95,115,97, - 102,101,108,121,46,95,95,101,110,116,101,114,95,95,99,1, - 0,0,0,0,0,0,0,3,0,0,0,17,0,0,0,71, - 0,0,0,115,98,0,0,0,122,82,124,0,106,0,125,2, - 116,1,100,1,100,2,132,0,124,1,68,0,131,1,131,1, - 114,64,121,14,116,2,106,3,124,2,106,4,61,0,87,0, - 113,80,4,0,116,5,107,10,114,60,1,0,1,0,1,0, - 89,0,113,80,88,0,110,16,116,6,100,3,124,2,106,4, - 124,2,106,7,131,3,1,0,87,0,100,0,100,4,124,0, - 106,0,95,8,88,0,100,0,83,0,41,5,78,99,1,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,115,0, - 0,0,115,22,0,0,0,124,0,93,14,125,1,124,1,100, - 0,107,9,86,0,1,0,113,2,100,0,83,0,41,1,78, - 114,10,0,0,0,41,2,90,2,46,48,90,3,97,114,103, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,250, - 9,60,103,101,110,101,120,112,114,62,65,1,0,0,115,2, - 0,0,0,4,0,122,45,95,105,110,115,116,97,108,108,101, - 100,95,115,97,102,101,108,121,46,95,95,101,120,105,116,95, - 95,46,60,108,111,99,97,108,115,62,46,60,103,101,110,101, - 120,112,114,62,122,18,105,109,112,111,114,116,32,123,33,114, - 125,32,35,32,123,33,114,125,70,41,9,114,99,0,0,0, - 218,3,97,110,121,114,14,0,0,0,114,80,0,0,0,114, - 15,0,0,0,114,55,0,0,0,114,69,0,0,0,114,94, - 0,0,0,114,100,0,0,0,41,3,114,26,0,0,0,114, - 47,0,0,0,114,83,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,48,0,0,0,62,1,0, - 0,115,18,0,0,0,0,1,2,1,6,1,18,1,2,1, - 14,1,14,1,8,2,20,2,122,26,95,105,110,115,116,97, - 108,108,101,100,95,115,97,102,101,108,121,46,95,95,101,120, - 105,116,95,95,78,41,6,114,1,0,0,0,114,0,0,0, - 0,114,2,0,0,0,114,27,0,0,0,114,46,0,0,0, - 114,48,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,97,0,0,0,49,1, - 0,0,115,6,0,0,0,8,2,8,4,8,7,114,97,0, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,4, - 0,0,0,64,0,0,0,115,114,0,0,0,101,0,90,1, - 100,0,90,2,100,1,90,3,100,2,100,2,100,2,100,3, - 156,3,100,4,100,5,132,2,90,4,100,6,100,7,132,0, - 90,5,100,8,100,9,132,0,90,6,101,7,100,10,100,11, - 132,0,131,1,90,8,101,8,106,9,100,12,100,11,132,0, - 131,1,90,8,101,7,100,13,100,14,132,0,131,1,90,10, - 101,7,100,15,100,16,132,0,131,1,90,11,101,11,106,9, - 100,17,100,16,132,0,131,1,90,11,100,2,83,0,41,18, - 218,10,77,111,100,117,108,101,83,112,101,99,97,208,5,0, - 0,84,104,101,32,115,112,101,99,105,102,105,99,97,116,105, - 111,110,32,102,111,114,32,97,32,109,111,100,117,108,101,44, - 32,117,115,101,100,32,102,111,114,32,108,111,97,100,105,110, - 103,46,10,10,32,32,32,32,65,32,109,111,100,117,108,101, - 39,115,32,115,112,101,99,32,105,115,32,116,104,101,32,115, - 111,117,114,99,101,32,102,111,114,32,105,110,102,111,114,109, - 97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32, - 109,111,100,117,108,101,46,32,32,70,111,114,10,32,32,32, - 32,100,97,116,97,32,97,115,115,111,99,105,97,116,101,100, - 32,119,105,116,104,32,116,104,101,32,109,111,100,117,108,101, - 44,32,105,110,99,108,117,100,105,110,103,32,115,111,117,114, - 99,101,44,32,117,115,101,32,116,104,101,32,115,112,101,99, - 39,115,10,32,32,32,32,108,111,97,100,101,114,46,10,10, - 32,32,32,32,96,110,97,109,101,96,32,105,115,32,116,104, - 101,32,97,98,115,111,108,117,116,101,32,110,97,109,101,32, - 111,102,32,116,104,101,32,109,111,100,117,108,101,46,32,32, - 96,108,111,97,100,101,114,96,32,105,115,32,116,104,101,32, - 108,111,97,100,101,114,10,32,32,32,32,116,111,32,117,115, - 101,32,119,104,101,110,32,108,111,97,100,105,110,103,32,116, - 104,101,32,109,111,100,117,108,101,46,32,32,96,112,97,114, - 101,110,116,96,32,105,115,32,116,104,101,32,110,97,109,101, - 32,111,102,32,116,104,101,10,32,32,32,32,112,97,99,107, - 97,103,101,32,116,104,101,32,109,111,100,117,108,101,32,105, - 115,32,105,110,46,32,32,84,104,101,32,112,97,114,101,110, - 116,32,105,115,32,100,101,114,105,118,101,100,32,102,114,111, - 109,32,116,104,101,32,110,97,109,101,46,10,10,32,32,32, - 32,96,105,115,95,112,97,99,107,97,103,101,96,32,100,101, - 116,101,114,109,105,110,101,115,32,105,102,32,116,104,101,32, - 109,111,100,117,108,101,32,105,115,32,99,111,110,115,105,100, - 101,114,101,100,32,97,32,112,97,99,107,97,103,101,32,111, - 114,10,32,32,32,32,110,111,116,46,32,32,79,110,32,109, - 111,100,117,108,101,115,32,116,104,105,115,32,105,115,32,114, - 101,102,108,101,99,116,101,100,32,98,121,32,116,104,101,32, - 96,95,95,112,97,116,104,95,95,96,32,97,116,116,114,105, - 98,117,116,101,46,10,10,32,32,32,32,96,111,114,105,103, - 105,110,96,32,105,115,32,116,104,101,32,115,112,101,99,105, - 102,105,99,32,108,111,99,97,116,105,111,110,32,117,115,101, - 100,32,98,121,32,116,104,101,32,108,111,97,100,101,114,32, - 102,114,111,109,32,119,104,105,99,104,32,116,111,10,32,32, - 32,32,108,111,97,100,32,116,104,101,32,109,111,100,117,108, - 101,44,32,105,102,32,116,104,97,116,32,105,110,102,111,114, - 109,97,116,105,111,110,32,105,115,32,97,118,97,105,108,97, - 98,108,101,46,32,32,87,104,101,110,32,102,105,108,101,110, - 97,109,101,32,105,115,10,32,32,32,32,115,101,116,44,32, - 111,114,105,103,105,110,32,119,105,108,108,32,109,97,116,99, - 104,46,10,10,32,32,32,32,96,104,97,115,95,108,111,99, - 97,116,105,111,110,96,32,105,110,100,105,99,97,116,101,115, - 32,116,104,97,116,32,97,32,115,112,101,99,39,115,32,34, - 111,114,105,103,105,110,34,32,114,101,102,108,101,99,116,115, - 32,97,32,108,111,99,97,116,105,111,110,46,10,32,32,32, - 32,87,104,101,110,32,116,104,105,115,32,105,115,32,84,114, - 117,101,44,32,96,95,95,102,105,108,101,95,95,96,32,97, - 116,116,114,105,98,117,116,101,32,111,102,32,116,104,101,32, - 109,111,100,117,108,101,32,105,115,32,115,101,116,46,10,10, - 32,32,32,32,96,99,97,99,104,101,100,96,32,105,115,32, - 116,104,101,32,108,111,99,97,116,105,111,110,32,111,102,32, - 116,104,101,32,99,97,99,104,101,100,32,98,121,116,101,99, - 111,100,101,32,102,105,108,101,44,32,105,102,32,97,110,121, - 46,32,32,73,116,10,32,32,32,32,99,111,114,114,101,115, - 112,111,110,100,115,32,116,111,32,116,104,101,32,96,95,95, - 99,97,99,104,101,100,95,95,96,32,97,116,116,114,105,98, - 117,116,101,46,10,10,32,32,32,32,96,115,117,98,109,111, - 100,117,108,101,95,115,101,97,114,99,104,95,108,111,99,97, - 116,105,111,110,115,96,32,105,115,32,116,104,101,32,115,101, - 113,117,101,110,99,101,32,111,102,32,112,97,116,104,32,101, - 110,116,114,105,101,115,32,116,111,10,32,32,32,32,115,101, - 97,114,99,104,32,119,104,101,110,32,105,109,112,111,114,116, - 105,110,103,32,115,117,98,109,111,100,117,108,101,115,46,32, - 32,73,102,32,115,101,116,44,32,105,115,95,112,97,99,107, - 97,103,101,32,115,104,111,117,108,100,32,98,101,10,32,32, - 32,32,84,114,117,101,45,45,97,110,100,32,70,97,108,115, - 101,32,111,116,104,101,114,119,105,115,101,46,10,10,32,32, - 32,32,80,97,99,107,97,103,101,115,32,97,114,101,32,115, - 105,109,112,108,121,32,109,111,100,117,108,101,115,32,116,104, - 97,116,32,40,109,97,121,41,32,104,97,118,101,32,115,117, - 98,109,111,100,117,108,101,115,46,32,32,73,102,32,97,32, - 115,112,101,99,10,32,32,32,32,104,97,115,32,97,32,110, - 111,110,45,78,111,110,101,32,118,97,108,117,101,32,105,110, - 32,96,115,117,98,109,111,100,117,108,101,95,115,101,97,114, - 99,104,95,108,111,99,97,116,105,111,110,115,96,44,32,116, - 104,101,32,105,109,112,111,114,116,10,32,32,32,32,115,121, - 115,116,101,109,32,119,105,108,108,32,99,111,110,115,105,100, - 101,114,32,109,111,100,117,108,101,115,32,108,111,97,100,101, - 100,32,102,114,111,109,32,116,104,101,32,115,112,101,99,32, - 97,115,32,112,97,99,107,97,103,101,115,46,10,10,32,32, - 32,32,79,110,108,121,32,102,105,110,100,101,114,115,32,40, - 115,101,101,32,105,109,112,111,114,116,108,105,98,46,97,98, - 99,46,77,101,116,97,80,97,116,104,70,105,110,100,101,114, - 32,97,110,100,10,32,32,32,32,105,109,112,111,114,116,108, - 105,98,46,97,98,99,46,80,97,116,104,69,110,116,114,121, - 70,105,110,100,101,114,41,32,115,104,111,117,108,100,32,109, - 111,100,105,102,121,32,77,111,100,117,108,101,83,112,101,99, - 32,105,110,115,116,97,110,99,101,115,46,10,10,32,32,32, - 32,78,41,3,218,6,111,114,105,103,105,110,218,12,108,111, - 97,100,101,114,95,115,116,97,116,101,218,10,105,115,95,112, - 97,99,107,97,103,101,99,3,0,0,0,3,0,0,0,6, - 0,0,0,2,0,0,0,67,0,0,0,115,54,0,0,0, - 124,1,124,0,95,0,124,2,124,0,95,1,124,3,124,0, - 95,2,124,4,124,0,95,3,124,5,114,32,103,0,110,2, - 100,0,124,0,95,4,100,1,124,0,95,5,100,0,124,0, - 95,6,100,0,83,0,41,2,78,70,41,7,114,15,0,0, - 0,114,94,0,0,0,114,104,0,0,0,114,105,0,0,0, - 218,26,115,117,98,109,111,100,117,108,101,95,115,101,97,114, - 99,104,95,108,111,99,97,116,105,111,110,115,218,13,95,115, - 101,116,95,102,105,108,101,97,116,116,114,218,7,95,99,97, - 99,104,101,100,41,6,114,26,0,0,0,114,15,0,0,0, - 114,94,0,0,0,114,104,0,0,0,114,105,0,0,0,114, - 106,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,27,0,0,0,113,1,0,0,115,14,0,0, - 0,0,2,6,1,6,1,6,1,6,1,14,3,6,1,122, - 19,77,111,100,117,108,101,83,112,101,99,46,95,95,105,110, - 105,116,95,95,99,1,0,0,0,0,0,0,0,2,0,0, - 0,6,0,0,0,67,0,0,0,115,102,0,0,0,100,1, - 160,0,124,0,106,1,161,1,100,2,160,0,124,0,106,2, - 161,1,103,2,125,1,124,0,106,3,100,0,107,9,114,52, - 124,1,160,4,100,3,160,0,124,0,106,3,161,1,161,1, - 1,0,124,0,106,5,100,0,107,9,114,80,124,1,160,4, - 100,4,160,0,124,0,106,5,161,1,161,1,1,0,100,5, - 160,0,124,0,106,6,106,7,100,6,160,8,124,1,161,1, - 161,2,83,0,41,7,78,122,9,110,97,109,101,61,123,33, - 114,125,122,11,108,111,97,100,101,114,61,123,33,114,125,122, - 11,111,114,105,103,105,110,61,123,33,114,125,122,29,115,117, - 98,109,111,100,117,108,101,95,115,101,97,114,99,104,95,108, - 111,99,97,116,105,111,110,115,61,123,125,122,6,123,125,40, - 123,125,41,122,2,44,32,41,9,114,38,0,0,0,114,15, - 0,0,0,114,94,0,0,0,114,104,0,0,0,218,6,97, - 112,112,101,110,100,114,107,0,0,0,218,9,95,95,99,108, - 97,115,115,95,95,114,1,0,0,0,218,4,106,111,105,110, - 41,2,114,26,0,0,0,114,47,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,40,0,0,0, - 125,1,0,0,115,16,0,0,0,0,1,10,1,14,1,10, - 1,18,1,10,1,8,1,10,1,122,19,77,111,100,117,108, - 101,83,112,101,99,46,95,95,114,101,112,114,95,95,99,2, - 0,0,0,0,0,0,0,3,0,0,0,11,0,0,0,67, - 0,0,0,115,102,0,0,0,124,0,106,0,125,2,121,70, - 124,0,106,1,124,1,106,1,107,2,111,76,124,0,106,2, - 124,1,106,2,107,2,111,76,124,0,106,3,124,1,106,3, - 107,2,111,76,124,2,124,1,106,0,107,2,111,76,124,0, - 106,4,124,1,106,4,107,2,111,76,124,0,106,5,124,1, - 106,5,107,2,83,0,4,0,116,6,107,10,114,96,1,0, - 1,0,1,0,100,1,83,0,88,0,100,0,83,0,41,2, - 78,70,41,7,114,107,0,0,0,114,15,0,0,0,114,94, - 0,0,0,114,104,0,0,0,218,6,99,97,99,104,101,100, - 218,12,104,97,115,95,108,111,99,97,116,105,111,110,114,91, - 0,0,0,41,3,114,26,0,0,0,90,5,111,116,104,101, - 114,90,4,115,109,115,108,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,6,95,95,101,113,95,95,135,1, - 0,0,115,20,0,0,0,0,1,6,1,2,1,12,1,12, - 1,12,1,10,1,12,1,12,1,14,1,122,17,77,111,100, - 117,108,101,83,112,101,99,46,95,95,101,113,95,95,99,1, + 80,0,0,0,86,2,0,0,115,30,0,0,0,0,2,6, + 1,10,1,16,1,10,1,12,1,10,1,10,1,14,2,14, + 1,4,1,14,1,12,4,14,2,22,1,114,80,0,0,0, + 99,1,0,0,0,0,0,0,0,2,0,0,0,27,0,0, + 0,67,0,0,0,115,206,0,0,0,124,0,106,0,160,1, + 124,0,106,2,161,1,1,0,116,3,106,4,124,0,106,2, + 25,0,125,1,116,5,124,1,100,1,100,0,131,3,100,0, + 107,8,114,76,121,12,124,0,106,0,124,1,95,6,87,0, + 110,20,4,0,116,7,107,10,114,74,1,0,1,0,1,0, + 89,0,110,2,88,0,116,5,124,1,100,2,100,0,131,3, + 100,0,107,8,114,154,121,40,124,1,106,8,124,1,95,9, + 116,10,124,1,100,3,131,2,115,130,124,0,106,2,160,11, + 100,4,161,1,100,5,25,0,124,1,95,9,87,0,110,20, + 4,0,116,7,107,10,114,152,1,0,1,0,1,0,89,0, + 110,2,88,0,116,5,124,1,100,6,100,0,131,3,100,0, + 107,8,114,202,121,10,124,0,124,1,95,12,87,0,110,20, + 4,0,116,7,107,10,114,200,1,0,1,0,1,0,89,0, + 110,2,88,0,124,1,83,0,41,7,78,114,85,0,0,0, + 114,130,0,0,0,114,127,0,0,0,114,117,0,0,0,114, + 19,0,0,0,114,89,0,0,0,41,13,114,93,0,0,0, + 114,137,0,0,0,114,15,0,0,0,114,14,0,0,0,114, + 79,0,0,0,114,6,0,0,0,114,85,0,0,0,114,90, + 0,0,0,114,1,0,0,0,114,130,0,0,0,114,4,0, + 0,0,114,118,0,0,0,114,89,0,0,0,41,2,114,82, + 0,0,0,114,83,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,25,95,108,111,97,100,95,98, + 97,99,107,119,97,114,100,95,99,111,109,112,97,116,105,98, + 108,101,110,2,0,0,115,40,0,0,0,0,4,14,2,12, + 1,16,1,2,1,12,1,14,1,6,1,16,1,2,4,8, + 1,10,1,22,1,14,1,6,1,16,1,2,1,10,1,14, + 1,6,1,114,139,0,0,0,99,1,0,0,0,0,0,0, + 0,2,0,0,0,11,0,0,0,67,0,0,0,115,118,0, + 0,0,124,0,106,0,100,0,107,9,114,30,116,1,124,0, + 106,0,100,1,131,2,115,30,116,2,124,0,131,1,83,0, + 116,3,124,0,131,1,125,1,116,4,124,1,131,1,143,54, + 1,0,124,0,106,0,100,0,107,8,114,84,124,0,106,5, + 100,0,107,8,114,96,116,6,100,2,124,0,106,7,100,3, + 141,2,130,1,110,12,124,0,106,0,160,8,124,1,161,1, + 1,0,87,0,100,0,81,0,82,0,88,0,116,9,106,10, + 124,0,106,7,25,0,83,0,41,4,78,114,135,0,0,0, + 122,14,109,105,115,115,105,110,103,32,108,111,97,100,101,114, + 41,1,114,15,0,0,0,41,11,114,93,0,0,0,114,4, + 0,0,0,114,139,0,0,0,114,136,0,0,0,114,96,0, + 0,0,114,106,0,0,0,114,70,0,0,0,114,15,0,0, + 0,114,135,0,0,0,114,14,0,0,0,114,79,0,0,0, + 41,2,114,82,0,0,0,114,83,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,218,14,95,108,111, + 97,100,95,117,110,108,111,99,107,101,100,139,2,0,0,115, + 20,0,0,0,0,2,10,2,12,1,8,2,8,1,10,1, + 10,1,10,1,16,3,22,5,114,140,0,0,0,99,1,0, + 0,0,0,0,0,0,1,0,0,0,9,0,0,0,67,0, + 0,0,115,30,0,0,0,116,0,124,0,106,1,131,1,143, + 10,1,0,116,2,124,0,131,1,83,0,81,0,82,0,88, + 0,100,1,83,0,41,2,122,191,82,101,116,117,114,110,32, + 97,32,110,101,119,32,109,111,100,117,108,101,32,111,98,106, + 101,99,116,44,32,108,111,97,100,101,100,32,98,121,32,116, + 104,101,32,115,112,101,99,39,115,32,108,111,97,100,101,114, + 46,10,10,32,32,32,32,84,104,101,32,109,111,100,117,108, + 101,32,105,115,32,110,111,116,32,97,100,100,101,100,32,116, + 111,32,105,116,115,32,112,97,114,101,110,116,46,10,10,32, + 32,32,32,73,102,32,97,32,109,111,100,117,108,101,32,105, + 115,32,97,108,114,101,97,100,121,32,105,110,32,115,121,115, + 46,109,111,100,117,108,101,115,44,32,116,104,97,116,32,101, + 120,105,115,116,105,110,103,32,109,111,100,117,108,101,32,103, + 101,116,115,10,32,32,32,32,99,108,111,98,98,101,114,101, + 100,46,10,10,32,32,32,32,78,41,3,114,42,0,0,0, + 114,15,0,0,0,114,140,0,0,0,41,1,114,82,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,81,0,0,0,162,2,0,0,115,4,0,0,0,0,9, + 12,1,114,81,0,0,0,99,0,0,0,0,0,0,0,0, + 0,0,0,0,4,0,0,0,64,0,0,0,115,136,0,0, + 0,101,0,90,1,100,0,90,2,100,1,90,3,101,4,100, + 2,100,3,132,0,131,1,90,5,101,6,100,19,100,5,100, + 6,132,1,131,1,90,7,101,6,100,20,100,7,100,8,132, + 1,131,1,90,8,101,6,100,9,100,10,132,0,131,1,90, + 9,101,6,100,11,100,12,132,0,131,1,90,10,101,6,101, + 11,100,13,100,14,132,0,131,1,131,1,90,12,101,6,101, + 11,100,15,100,16,132,0,131,1,131,1,90,13,101,6,101, + 11,100,17,100,18,132,0,131,1,131,1,90,14,101,6,101, + 15,131,1,90,16,100,4,83,0,41,21,218,15,66,117,105, + 108,116,105,110,73,109,112,111,114,116,101,114,122,144,77,101, + 116,97,32,112,97,116,104,32,105,109,112,111,114,116,32,102, + 111,114,32,98,117,105,108,116,45,105,110,32,109,111,100,117, + 108,101,115,46,10,10,32,32,32,32,65,108,108,32,109,101, + 116,104,111,100,115,32,97,114,101,32,101,105,116,104,101,114, + 32,99,108,97,115,115,32,111,114,32,115,116,97,116,105,99, + 32,109,101,116,104,111,100,115,32,116,111,32,97,118,111,105, + 100,32,116,104,101,32,110,101,101,100,32,116,111,10,32,32, + 32,32,105,110,115,116,97,110,116,105,97,116,101,32,116,104, + 101,32,99,108,97,115,115,46,10,10,32,32,32,32,99,1, 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, - 0,0,0,115,58,0,0,0,124,0,106,0,100,0,107,8, - 114,52,124,0,106,1,100,0,107,9,114,52,124,0,106,2, - 114,52,116,3,100,0,107,8,114,38,116,4,130,1,116,3, - 160,5,124,0,106,1,161,1,124,0,95,0,124,0,106,0, - 83,0,41,1,78,41,6,114,109,0,0,0,114,104,0,0, - 0,114,108,0,0,0,218,19,95,98,111,111,116,115,116,114, - 97,112,95,101,120,116,101,114,110,97,108,218,19,78,111,116, - 73,109,112,108,101,109,101,110,116,101,100,69,114,114,111,114, - 90,11,95,103,101,116,95,99,97,99,104,101,100,41,1,114, - 26,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,113,0,0,0,147,1,0,0,115,12,0,0, - 0,0,2,10,1,16,1,8,1,4,1,14,1,122,17,77, - 111,100,117,108,101,83,112,101,99,46,99,97,99,104,101,100, - 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, - 0,67,0,0,0,115,10,0,0,0,124,1,124,0,95,0, - 100,0,83,0,41,1,78,41,1,114,109,0,0,0,41,2, - 114,26,0,0,0,114,113,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,113,0,0,0,156,1, - 0,0,115,2,0,0,0,0,2,99,1,0,0,0,0,0, - 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,36, - 0,0,0,124,0,106,0,100,1,107,8,114,26,124,0,106, - 1,160,2,100,2,161,1,100,3,25,0,83,0,124,0,106, - 1,83,0,100,1,83,0,41,4,122,32,84,104,101,32,110, - 97,109,101,32,111,102,32,116,104,101,32,109,111,100,117,108, - 101,39,115,32,112,97,114,101,110,116,46,78,218,1,46,114, - 19,0,0,0,41,3,114,107,0,0,0,114,15,0,0,0, - 218,10,114,112,97,114,116,105,116,105,111,110,41,1,114,26, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,6,112,97,114,101,110,116,160,1,0,0,115,6, - 0,0,0,0,3,10,1,16,2,122,17,77,111,100,117,108, - 101,83,112,101,99,46,112,97,114,101,110,116,99,1,0,0, - 0,0,0,0,0,1,0,0,0,1,0,0,0,67,0,0, - 0,115,6,0,0,0,124,0,106,0,83,0,41,1,78,41, - 1,114,108,0,0,0,41,1,114,26,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,114,0,0, - 0,168,1,0,0,115,2,0,0,0,0,2,122,23,77,111, - 100,117,108,101,83,112,101,99,46,104,97,115,95,108,111,99, - 97,116,105,111,110,99,2,0,0,0,0,0,0,0,2,0, - 0,0,2,0,0,0,67,0,0,0,115,14,0,0,0,116, - 0,124,1,131,1,124,0,95,1,100,0,83,0,41,1,78, - 41,2,218,4,98,111,111,108,114,108,0,0,0,41,2,114, - 26,0,0,0,218,5,118,97,108,117,101,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,114,0,0,0,172, - 1,0,0,115,2,0,0,0,0,2,41,12,114,1,0,0, - 0,114,0,0,0,0,114,2,0,0,0,114,3,0,0,0, - 114,27,0,0,0,114,40,0,0,0,114,115,0,0,0,218, - 8,112,114,111,112,101,114,116,121,114,113,0,0,0,218,6, - 115,101,116,116,101,114,114,120,0,0,0,114,114,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,103,0,0,0,76,1,0,0,115,18,0, - 0,0,12,37,4,1,14,11,8,10,8,12,12,9,14,4, - 12,8,12,4,114,103,0,0,0,41,2,114,104,0,0,0, - 114,106,0,0,0,99,2,0,0,0,2,0,0,0,6,0, - 0,0,14,0,0,0,67,0,0,0,115,154,0,0,0,116, - 0,124,1,100,1,131,2,114,74,116,1,100,2,107,8,114, - 22,116,2,130,1,116,1,106,3,125,4,124,3,100,2,107, - 8,114,48,124,4,124,0,124,1,100,3,141,2,83,0,124, - 3,114,56,103,0,110,2,100,2,125,5,124,4,124,0,124, - 1,124,5,100,4,141,3,83,0,124,3,100,2,107,8,114, - 138,116,0,124,1,100,5,131,2,114,134,121,14,124,1,160, - 4,124,0,161,1,125,3,87,0,113,138,4,0,116,5,107, - 10,114,130,1,0,1,0,1,0,100,2,125,3,89,0,113, - 138,88,0,110,4,100,6,125,3,116,6,124,0,124,1,124, - 2,124,3,100,7,141,4,83,0,41,8,122,53,82,101,116, - 117,114,110,32,97,32,109,111,100,117,108,101,32,115,112,101, - 99,32,98,97,115,101,100,32,111,110,32,118,97,114,105,111, - 117,115,32,108,111,97,100,101,114,32,109,101,116,104,111,100, - 115,46,90,12,103,101,116,95,102,105,108,101,110,97,109,101, - 78,41,1,114,94,0,0,0,41,2,114,94,0,0,0,114, - 107,0,0,0,114,106,0,0,0,70,41,2,114,104,0,0, - 0,114,106,0,0,0,41,7,114,4,0,0,0,114,116,0, - 0,0,114,117,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,106,0,0,0,114,71,0,0,0,114,103,0,0,0,41, - 6,114,15,0,0,0,114,94,0,0,0,114,104,0,0,0, - 114,106,0,0,0,114,125,0,0,0,90,6,115,101,97,114, - 99,104,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,79,0,0,0,177,1,0,0,115,34,0,0,0,0, - 2,10,1,8,1,4,1,6,2,8,1,12,1,12,1,6, - 1,8,2,8,1,10,1,2,1,14,1,14,1,12,3,4, - 2,114,79,0,0,0,99,3,0,0,0,0,0,0,0,8, - 0,0,0,53,0,0,0,67,0,0,0,115,56,1,0,0, - 121,10,124,0,106,0,125,3,87,0,110,20,4,0,116,1, - 107,10,114,30,1,0,1,0,1,0,89,0,110,14,88,0, - 124,3,100,0,107,9,114,44,124,3,83,0,124,0,106,2, - 125,4,124,1,100,0,107,8,114,90,121,10,124,0,106,3, - 125,1,87,0,110,20,4,0,116,1,107,10,114,88,1,0, - 1,0,1,0,89,0,110,2,88,0,121,10,124,0,106,4, - 125,5,87,0,110,24,4,0,116,1,107,10,114,124,1,0, - 1,0,1,0,100,0,125,5,89,0,110,2,88,0,124,2, - 100,0,107,8,114,184,124,5,100,0,107,8,114,180,121,10, - 124,1,106,5,125,2,87,0,113,184,4,0,116,1,107,10, - 114,176,1,0,1,0,1,0,100,0,125,2,89,0,113,184, - 88,0,110,4,124,5,125,2,121,10,124,0,106,6,125,6, - 87,0,110,24,4,0,116,1,107,10,114,218,1,0,1,0, - 1,0,100,0,125,6,89,0,110,2,88,0,121,14,116,7, - 124,0,106,8,131,1,125,7,87,0,110,26,4,0,116,1, - 107,10,144,1,114,4,1,0,1,0,1,0,100,0,125,7, - 89,0,110,2,88,0,116,9,124,4,124,1,124,2,100,1, - 141,3,125,3,124,5,100,0,107,8,144,1,114,34,100,2, - 110,2,100,3,124,3,95,10,124,6,124,3,95,11,124,7, - 124,3,95,12,124,3,83,0,41,4,78,41,1,114,104,0, - 0,0,70,84,41,13,114,90,0,0,0,114,91,0,0,0, - 114,1,0,0,0,114,86,0,0,0,114,93,0,0,0,90, - 7,95,79,82,73,71,73,78,218,10,95,95,99,97,99,104, - 101,100,95,95,218,4,108,105,115,116,218,8,95,95,112,97, - 116,104,95,95,114,103,0,0,0,114,108,0,0,0,114,113, - 0,0,0,114,107,0,0,0,41,8,114,84,0,0,0,114, - 94,0,0,0,114,104,0,0,0,114,83,0,0,0,114,15, - 0,0,0,90,8,108,111,99,97,116,105,111,110,114,113,0, - 0,0,114,107,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,17,95,115,112,101,99,95,102,114, - 111,109,95,109,111,100,117,108,101,203,1,0,0,115,72,0, - 0,0,0,2,2,1,10,1,14,1,6,2,8,1,4,2, - 6,1,8,1,2,1,10,1,14,2,6,1,2,1,10,1, - 14,1,10,1,8,1,8,1,2,1,10,1,14,1,12,2, - 4,1,2,1,10,1,14,1,10,1,2,1,14,1,16,1, - 10,2,14,1,20,1,6,1,6,1,114,129,0,0,0,70, - 41,1,218,8,111,118,101,114,114,105,100,101,99,2,0,0, - 0,1,0,0,0,5,0,0,0,59,0,0,0,67,0,0, - 0,115,212,1,0,0,124,2,115,20,116,0,124,1,100,1, - 100,0,131,3,100,0,107,8,114,54,121,12,124,0,106,1, - 124,1,95,2,87,0,110,20,4,0,116,3,107,10,114,52, - 1,0,1,0,1,0,89,0,110,2,88,0,124,2,115,74, - 116,0,124,1,100,2,100,0,131,3,100,0,107,8,114,166, - 124,0,106,4,125,3,124,3,100,0,107,8,114,134,124,0, - 106,5,100,0,107,9,114,134,116,6,100,0,107,8,114,110, - 116,7,130,1,116,6,106,8,125,4,124,4,160,9,124,4, - 161,1,125,3,124,0,106,5,124,3,95,10,121,10,124,3, - 124,1,95,11,87,0,110,20,4,0,116,3,107,10,114,164, - 1,0,1,0,1,0,89,0,110,2,88,0,124,2,115,186, - 116,0,124,1,100,3,100,0,131,3,100,0,107,8,114,220, - 121,12,124,0,106,12,124,1,95,13,87,0,110,20,4,0, - 116,3,107,10,114,218,1,0,1,0,1,0,89,0,110,2, - 88,0,121,10,124,0,124,1,95,14,87,0,110,20,4,0, - 116,3,107,10,114,250,1,0,1,0,1,0,89,0,110,2, - 88,0,124,2,144,1,115,20,116,0,124,1,100,4,100,0, - 131,3,100,0,107,8,144,1,114,68,124,0,106,5,100,0, - 107,9,144,1,114,68,121,12,124,0,106,5,124,1,95,15, - 87,0,110,22,4,0,116,3,107,10,144,1,114,66,1,0, - 1,0,1,0,89,0,110,2,88,0,124,0,106,16,144,1, - 114,208,124,2,144,1,115,100,116,0,124,1,100,5,100,0, - 131,3,100,0,107,8,144,1,114,136,121,12,124,0,106,17, - 124,1,95,18,87,0,110,22,4,0,116,3,107,10,144,1, - 114,134,1,0,1,0,1,0,89,0,110,2,88,0,124,2, - 144,1,115,160,116,0,124,1,100,6,100,0,131,3,100,0, - 107,8,144,1,114,208,124,0,106,19,100,0,107,9,144,1, - 114,208,121,12,124,0,106,19,124,1,95,20,87,0,110,22, - 4,0,116,3,107,10,144,1,114,206,1,0,1,0,1,0, - 89,0,110,2,88,0,124,1,83,0,41,7,78,114,1,0, - 0,0,114,86,0,0,0,218,11,95,95,112,97,99,107,97, - 103,101,95,95,114,128,0,0,0,114,93,0,0,0,114,126, - 0,0,0,41,21,114,6,0,0,0,114,15,0,0,0,114, - 1,0,0,0,114,91,0,0,0,114,94,0,0,0,114,107, - 0,0,0,114,116,0,0,0,114,117,0,0,0,218,16,95, - 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,218, - 7,95,95,110,101,119,95,95,90,5,95,112,97,116,104,114, - 86,0,0,0,114,120,0,0,0,114,131,0,0,0,114,90, - 0,0,0,114,128,0,0,0,114,114,0,0,0,114,104,0, - 0,0,114,93,0,0,0,114,113,0,0,0,114,126,0,0, - 0,41,5,114,83,0,0,0,114,84,0,0,0,114,130,0, - 0,0,114,94,0,0,0,114,132,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,218,18,95,105,110, - 105,116,95,109,111,100,117,108,101,95,97,116,116,114,115,248, - 1,0,0,115,92,0,0,0,0,4,20,1,2,1,12,1, - 14,1,6,2,20,1,6,1,8,2,10,1,8,1,4,1, - 6,2,10,1,8,1,2,1,10,1,14,1,6,2,20,1, - 2,1,12,1,14,1,6,2,2,1,10,1,14,1,6,2, - 24,1,12,1,2,1,12,1,16,1,6,2,8,1,24,1, - 2,1,12,1,16,1,6,2,24,1,12,1,2,1,12,1, - 16,1,6,1,114,134,0,0,0,99,1,0,0,0,0,0, - 0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,82, - 0,0,0,100,1,125,1,116,0,124,0,106,1,100,2,131, - 2,114,30,124,0,106,1,160,2,124,0,161,1,125,1,110, - 20,116,0,124,0,106,1,100,3,131,2,114,50,116,3,100, - 4,131,1,130,1,124,1,100,1,107,8,114,68,116,4,124, - 0,106,5,131,1,125,1,116,6,124,0,124,1,131,2,1, - 0,124,1,83,0,41,5,122,43,67,114,101,97,116,101,32, - 97,32,109,111,100,117,108,101,32,98,97,115,101,100,32,111, - 110,32,116,104,101,32,112,114,111,118,105,100,101,100,32,115, - 112,101,99,46,78,218,13,99,114,101,97,116,101,95,109,111, - 100,117,108,101,218,11,101,120,101,99,95,109,111,100,117,108, - 101,122,66,108,111,97,100,101,114,115,32,116,104,97,116,32, - 100,101,102,105,110,101,32,101,120,101,99,95,109,111,100,117, - 108,101,40,41,32,109,117,115,116,32,97,108,115,111,32,100, - 101,102,105,110,101,32,99,114,101,97,116,101,95,109,111,100, - 117,108,101,40,41,41,7,114,4,0,0,0,114,94,0,0, - 0,114,135,0,0,0,114,71,0,0,0,114,16,0,0,0, - 114,15,0,0,0,114,134,0,0,0,41,2,114,83,0,0, - 0,114,84,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,218,16,109,111,100,117,108,101,95,102,114, - 111,109,95,115,112,101,99,52,2,0,0,115,18,0,0,0, - 0,3,4,1,12,3,14,1,12,1,8,2,8,1,10,1, - 10,1,114,137,0,0,0,99,1,0,0,0,0,0,0,0, - 2,0,0,0,4,0,0,0,67,0,0,0,115,106,0,0, - 0,124,0,106,0,100,1,107,8,114,14,100,2,110,4,124, - 0,106,0,125,1,124,0,106,1,100,1,107,8,114,66,124, - 0,106,2,100,1,107,8,114,50,100,3,160,3,124,1,161, - 1,83,0,100,4,160,3,124,1,124,0,106,2,161,2,83, - 0,110,36,124,0,106,4,114,86,100,5,160,3,124,1,124, - 0,106,1,161,2,83,0,100,6,160,3,124,0,106,0,124, - 0,106,1,161,2,83,0,100,1,83,0,41,7,122,38,82, - 101,116,117,114,110,32,116,104,101,32,114,101,112,114,32,116, - 111,32,117,115,101,32,102,111,114,32,116,104,101,32,109,111, - 100,117,108,101,46,78,114,88,0,0,0,122,13,60,109,111, - 100,117,108,101,32,123,33,114,125,62,122,20,60,109,111,100, - 117,108,101,32,123,33,114,125,32,40,123,33,114,125,41,62, - 122,23,60,109,111,100,117,108,101,32,123,33,114,125,32,102, - 114,111,109,32,123,33,114,125,62,122,18,60,109,111,100,117, - 108,101,32,123,33,114,125,32,40,123,125,41,62,41,5,114, - 15,0,0,0,114,104,0,0,0,114,94,0,0,0,114,38, - 0,0,0,114,114,0,0,0,41,2,114,83,0,0,0,114, - 15,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,92,0,0,0,69,2,0,0,115,16,0,0, - 0,0,3,20,1,10,1,10,1,10,2,16,2,6,1,14, - 2,114,92,0,0,0,99,2,0,0,0,0,0,0,0,4, - 0,0,0,12,0,0,0,67,0,0,0,115,178,0,0,0, - 124,0,106,0,125,2,116,1,124,2,131,1,143,148,1,0, - 116,2,106,3,160,4,124,2,161,1,124,1,107,9,114,54, - 100,1,160,5,124,2,161,1,125,3,116,6,124,3,124,2, - 100,2,141,2,130,1,124,0,106,7,100,3,107,8,114,106, - 124,0,106,8,100,3,107,8,114,88,116,6,100,4,124,0, - 106,0,100,2,141,2,130,1,116,9,124,0,124,1,100,5, - 100,6,141,3,1,0,124,1,83,0,116,9,124,0,124,1, - 100,5,100,6,141,3,1,0,116,10,124,0,106,7,100,7, - 131,2,115,146,124,0,106,7,160,11,124,2,161,1,1,0, - 110,12,124,0,106,7,160,12,124,1,161,1,1,0,87,0, - 100,3,81,0,82,0,88,0,116,2,106,3,124,2,25,0, - 83,0,41,8,122,70,69,120,101,99,117,116,101,32,116,104, - 101,32,115,112,101,99,39,115,32,115,112,101,99,105,102,105, - 101,100,32,109,111,100,117,108,101,32,105,110,32,97,110,32, - 101,120,105,115,116,105,110,103,32,109,111,100,117,108,101,39, - 115,32,110,97,109,101,115,112,97,99,101,46,122,30,109,111, - 100,117,108,101,32,123,33,114,125,32,110,111,116,32,105,110, - 32,115,121,115,46,109,111,100,117,108,101,115,41,1,114,15, - 0,0,0,78,122,14,109,105,115,115,105,110,103,32,108,111, - 97,100,101,114,84,41,1,114,130,0,0,0,114,136,0,0, - 0,41,13,114,15,0,0,0,114,42,0,0,0,114,14,0, - 0,0,114,80,0,0,0,114,30,0,0,0,114,38,0,0, - 0,114,71,0,0,0,114,94,0,0,0,114,107,0,0,0, - 114,134,0,0,0,114,4,0,0,0,218,11,108,111,97,100, - 95,109,111,100,117,108,101,114,136,0,0,0,41,4,114,83, - 0,0,0,114,84,0,0,0,114,15,0,0,0,218,3,109, - 115,103,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,81,0,0,0,86,2,0,0,115,30,0,0,0,0, - 2,6,1,10,1,16,1,10,1,12,1,10,1,10,1,14, - 2,14,1,4,1,14,1,12,4,14,2,22,1,114,81,0, - 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,27, - 0,0,0,67,0,0,0,115,206,0,0,0,124,0,106,0, - 160,1,124,0,106,2,161,1,1,0,116,3,106,4,124,0, - 106,2,25,0,125,1,116,5,124,1,100,1,100,0,131,3, - 100,0,107,8,114,76,121,12,124,0,106,0,124,1,95,6, - 87,0,110,20,4,0,116,7,107,10,114,74,1,0,1,0, - 1,0,89,0,110,2,88,0,116,5,124,1,100,2,100,0, - 131,3,100,0,107,8,114,154,121,40,124,1,106,8,124,1, - 95,9,116,10,124,1,100,3,131,2,115,130,124,0,106,2, - 160,11,100,4,161,1,100,5,25,0,124,1,95,9,87,0, - 110,20,4,0,116,7,107,10,114,152,1,0,1,0,1,0, - 89,0,110,2,88,0,116,5,124,1,100,6,100,0,131,3, - 100,0,107,8,114,202,121,10,124,0,124,1,95,12,87,0, - 110,20,4,0,116,7,107,10,114,200,1,0,1,0,1,0, - 89,0,110,2,88,0,124,1,83,0,41,7,78,114,86,0, - 0,0,114,131,0,0,0,114,128,0,0,0,114,118,0,0, - 0,114,19,0,0,0,114,90,0,0,0,41,13,114,94,0, - 0,0,114,138,0,0,0,114,15,0,0,0,114,14,0,0, - 0,114,80,0,0,0,114,6,0,0,0,114,86,0,0,0, - 114,91,0,0,0,114,1,0,0,0,114,131,0,0,0,114, - 4,0,0,0,114,119,0,0,0,114,90,0,0,0,41,2, - 114,83,0,0,0,114,84,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,25,95,108,111,97,100, - 95,98,97,99,107,119,97,114,100,95,99,111,109,112,97,116, - 105,98,108,101,110,2,0,0,115,40,0,0,0,0,4,14, - 2,12,1,16,1,2,1,12,1,14,1,6,1,16,1,2, - 4,8,1,10,1,22,1,14,1,6,1,16,1,2,1,10, - 1,14,1,6,1,114,140,0,0,0,99,1,0,0,0,0, - 0,0,0,2,0,0,0,11,0,0,0,67,0,0,0,115, - 118,0,0,0,124,0,106,0,100,0,107,9,114,30,116,1, - 124,0,106,0,100,1,131,2,115,30,116,2,124,0,131,1, - 83,0,116,3,124,0,131,1,125,1,116,4,124,1,131,1, - 143,54,1,0,124,0,106,0,100,0,107,8,114,84,124,0, - 106,5,100,0,107,8,114,96,116,6,100,2,124,0,106,7, - 100,3,141,2,130,1,110,12,124,0,106,0,160,8,124,1, - 161,1,1,0,87,0,100,0,81,0,82,0,88,0,116,9, - 106,10,124,0,106,7,25,0,83,0,41,4,78,114,136,0, - 0,0,122,14,109,105,115,115,105,110,103,32,108,111,97,100, - 101,114,41,1,114,15,0,0,0,41,11,114,94,0,0,0, - 114,4,0,0,0,114,140,0,0,0,114,137,0,0,0,114, - 97,0,0,0,114,107,0,0,0,114,71,0,0,0,114,15, - 0,0,0,114,136,0,0,0,114,14,0,0,0,114,80,0, - 0,0,41,2,114,83,0,0,0,114,84,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,218,14,95, - 108,111,97,100,95,117,110,108,111,99,107,101,100,139,2,0, - 0,115,20,0,0,0,0,2,10,2,12,1,8,2,8,1, - 10,1,10,1,10,1,16,3,22,5,114,141,0,0,0,99, - 1,0,0,0,0,0,0,0,1,0,0,0,9,0,0,0, - 67,0,0,0,115,30,0,0,0,116,0,124,0,106,1,131, - 1,143,10,1,0,116,2,124,0,131,1,83,0,81,0,82, - 0,88,0,100,1,83,0,41,2,122,191,82,101,116,117,114, - 110,32,97,32,110,101,119,32,109,111,100,117,108,101,32,111, - 98,106,101,99,116,44,32,108,111,97,100,101,100,32,98,121, - 32,116,104,101,32,115,112,101,99,39,115,32,108,111,97,100, - 101,114,46,10,10,32,32,32,32,84,104,101,32,109,111,100, - 117,108,101,32,105,115,32,110,111,116,32,97,100,100,101,100, - 32,116,111,32,105,116,115,32,112,97,114,101,110,116,46,10, - 10,32,32,32,32,73,102,32,97,32,109,111,100,117,108,101, - 32,105,115,32,97,108,114,101,97,100,121,32,105,110,32,115, - 121,115,46,109,111,100,117,108,101,115,44,32,116,104,97,116, - 32,101,120,105,115,116,105,110,103,32,109,111,100,117,108,101, - 32,103,101,116,115,10,32,32,32,32,99,108,111,98,98,101, - 114,101,100,46,10,10,32,32,32,32,78,41,3,114,42,0, - 0,0,114,15,0,0,0,114,141,0,0,0,41,1,114,83, + 0,0,0,115,12,0,0,0,100,1,160,0,124,0,106,1, + 161,1,83,0,41,2,122,115,82,101,116,117,114,110,32,114, + 101,112,114,32,102,111,114,32,116,104,101,32,109,111,100,117, + 108,101,46,10,10,32,32,32,32,32,32,32,32,84,104,101, + 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, + 99,97,116,101,100,46,32,32,84,104,101,32,105,109,112,111, + 114,116,32,109,97,99,104,105,110,101,114,121,32,100,111,101, + 115,32,116,104,101,32,106,111,98,32,105,116,115,101,108,102, + 46,10,10,32,32,32,32,32,32,32,32,122,24,60,109,111, + 100,117,108,101,32,123,33,114,125,32,40,98,117,105,108,116, + 45,105,110,41,62,41,2,114,38,0,0,0,114,1,0,0, + 0,41,1,114,83,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,86,0,0,0,186,2,0,0, + 115,2,0,0,0,0,7,122,27,66,117,105,108,116,105,110, + 73,109,112,111,114,116,101,114,46,109,111,100,117,108,101,95, + 114,101,112,114,78,99,4,0,0,0,0,0,0,0,4,0, + 0,0,5,0,0,0,67,0,0,0,115,44,0,0,0,124, + 2,100,0,107,9,114,12,100,0,83,0,116,0,160,1,124, + 1,161,1,114,36,116,2,124,1,124,0,100,1,100,2,141, + 3,83,0,100,0,83,0,100,0,83,0,41,3,78,122,8, + 98,117,105,108,116,45,105,110,41,1,114,103,0,0,0,41, + 3,114,49,0,0,0,90,10,105,115,95,98,117,105,108,116, + 105,110,114,78,0,0,0,41,4,218,3,99,108,115,114,71, + 0,0,0,218,4,112,97,116,104,218,6,116,97,114,103,101, + 116,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,9,102,105,110,100,95,115,112,101,99,195,2,0,0,115, + 10,0,0,0,0,2,8,1,4,1,10,1,14,2,122,25, + 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, + 102,105,110,100,95,115,112,101,99,99,3,0,0,0,0,0, + 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,30, + 0,0,0,124,0,160,0,124,1,124,2,161,2,125,3,124, + 3,100,1,107,9,114,26,124,3,106,1,83,0,100,1,83, + 0,41,2,122,175,70,105,110,100,32,116,104,101,32,98,117, + 105,108,116,45,105,110,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,73,102,32,39,112,97,116,104, + 39,32,105,115,32,101,118,101,114,32,115,112,101,99,105,102, + 105,101,100,32,116,104,101,110,32,116,104,101,32,115,101,97, + 114,99,104,32,105,115,32,99,111,110,115,105,100,101,114,101, + 100,32,97,32,102,97,105,108,117,114,101,46,10,10,32,32, + 32,32,32,32,32,32,84,104,105,115,32,109,101,116,104,111, + 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, + 32,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, + 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, + 32,32,32,32,78,41,2,114,145,0,0,0,114,93,0,0, + 0,41,4,114,142,0,0,0,114,71,0,0,0,114,143,0, + 0,0,114,82,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,218,11,102,105,110,100,95,109,111,100, + 117,108,101,204,2,0,0,115,4,0,0,0,0,9,12,1, + 122,27,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 114,46,102,105,110,100,95,109,111,100,117,108,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,67,0, + 0,0,115,46,0,0,0,124,1,106,0,116,1,106,2,107, + 7,114,34,116,3,100,1,160,4,124,1,106,0,161,1,124, + 1,106,0,100,2,141,2,130,1,116,5,116,6,106,7,124, + 1,131,2,83,0,41,3,122,24,67,114,101,97,116,101,32, + 97,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, + 101,122,29,123,33,114,125,32,105,115,32,110,111,116,32,97, + 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, + 41,1,114,15,0,0,0,41,8,114,15,0,0,0,114,14, + 0,0,0,114,69,0,0,0,114,70,0,0,0,114,38,0, + 0,0,114,59,0,0,0,114,49,0,0,0,90,14,99,114, + 101,97,116,101,95,98,117,105,108,116,105,110,41,2,114,26, + 0,0,0,114,82,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,134,0,0,0,216,2,0,0, + 115,8,0,0,0,0,3,12,1,12,1,10,1,122,29,66, + 117,105,108,116,105,110,73,109,112,111,114,116,101,114,46,99, + 114,101,97,116,101,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, + 0,115,16,0,0,0,116,0,116,1,106,2,124,1,131,2, + 1,0,100,1,83,0,41,2,122,22,69,120,101,99,32,97, + 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, + 78,41,3,114,59,0,0,0,114,49,0,0,0,90,12,101, + 120,101,99,95,98,117,105,108,116,105,110,41,2,114,26,0, + 0,0,114,83,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,135,0,0,0,224,2,0,0,115, + 2,0,0,0,0,3,122,27,66,117,105,108,116,105,110,73, + 109,112,111,114,116,101,114,46,101,120,101,99,95,109,111,100, + 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, + 0,41,2,122,57,82,101,116,117,114,110,32,78,111,110,101, + 32,97,115,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,115,32,100,111,32,110,111,116,32,104,97,118,101, + 32,99,111,100,101,32,111,98,106,101,99,116,115,46,78,114, + 10,0,0,0,41,2,114,142,0,0,0,114,71,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, + 8,103,101,116,95,99,111,100,101,229,2,0,0,115,2,0, + 0,0,0,4,122,24,66,117,105,108,116,105,110,73,109,112, + 111,114,116,101,114,46,103,101,116,95,99,111,100,101,99,2, + 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, + 0,0,0,115,4,0,0,0,100,1,83,0,41,2,122,56, + 82,101,116,117,114,110,32,78,111,110,101,32,97,115,32,98, + 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32, + 100,111,32,110,111,116,32,104,97,118,101,32,115,111,117,114, + 99,101,32,99,111,100,101,46,78,114,10,0,0,0,41,2, + 114,142,0,0,0,114,71,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,218,10,103,101,116,95,115, + 111,117,114,99,101,235,2,0,0,115,2,0,0,0,0,4, + 122,26,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 114,46,103,101,116,95,115,111,117,114,99,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,83,0,41,2,122,52,82,101, + 116,117,114,110,32,70,97,108,115,101,32,97,115,32,98,117, + 105,108,116,45,105,110,32,109,111,100,117,108,101,115,32,97, + 114,101,32,110,101,118,101,114,32,112,97,99,107,97,103,101, + 115,46,70,114,10,0,0,0,41,2,114,142,0,0,0,114, + 71,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,105,0,0,0,241,2,0,0,115,2,0,0, + 0,0,4,122,26,66,117,105,108,116,105,110,73,109,112,111, + 114,116,101,114,46,105,115,95,112,97,99,107,97,103,101,41, + 2,78,78,41,1,78,41,17,114,1,0,0,0,114,0,0, + 0,0,114,2,0,0,0,114,3,0,0,0,218,12,115,116, + 97,116,105,99,109,101,116,104,111,100,114,86,0,0,0,218, + 11,99,108,97,115,115,109,101,116,104,111,100,114,145,0,0, + 0,114,146,0,0,0,114,134,0,0,0,114,135,0,0,0, + 114,74,0,0,0,114,147,0,0,0,114,148,0,0,0,114, + 105,0,0,0,114,84,0,0,0,114,137,0,0,0,114,10, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,82,0,0,0,162,2,0,0,115,4,0,0,0, - 0,9,12,1,114,82,0,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,4,0,0,0,64,0,0,0,115,136, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,101, - 4,100,2,100,3,132,0,131,1,90,5,101,6,100,19,100, - 5,100,6,132,1,131,1,90,7,101,6,100,20,100,7,100, - 8,132,1,131,1,90,8,101,6,100,9,100,10,132,0,131, - 1,90,9,101,6,100,11,100,12,132,0,131,1,90,10,101, - 6,101,11,100,13,100,14,132,0,131,1,131,1,90,12,101, - 6,101,11,100,15,100,16,132,0,131,1,131,1,90,13,101, - 6,101,11,100,17,100,18,132,0,131,1,131,1,90,14,101, - 6,101,15,131,1,90,16,100,4,83,0,41,21,218,15,66, - 117,105,108,116,105,110,73,109,112,111,114,116,101,114,122,144, - 77,101,116,97,32,112,97,116,104,32,105,109,112,111,114,116, - 32,102,111,114,32,98,117,105,108,116,45,105,110,32,109,111, - 100,117,108,101,115,46,10,10,32,32,32,32,65,108,108,32, - 109,101,116,104,111,100,115,32,97,114,101,32,101,105,116,104, - 101,114,32,99,108,97,115,115,32,111,114,32,115,116,97,116, - 105,99,32,109,101,116,104,111,100,115,32,116,111,32,97,118, - 111,105,100,32,116,104,101,32,110,101,101,100,32,116,111,10, - 32,32,32,32,105,110,115,116,97,110,116,105,97,116,101,32, - 116,104,101,32,99,108,97,115,115,46,10,10,32,32,32,32, - 99,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0, - 0,67,0,0,0,115,12,0,0,0,100,1,160,0,124,0, - 106,1,161,1,83,0,41,2,122,115,82,101,116,117,114,110, - 32,114,101,112,114,32,102,111,114,32,116,104,101,32,109,111, - 100,117,108,101,46,10,10,32,32,32,32,32,32,32,32,84, - 104,101,32,109,101,116,104,111,100,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,46,32,32,84,104,101,32,105,109, - 112,111,114,116,32,109,97,99,104,105,110,101,114,121,32,100, - 111,101,115,32,116,104,101,32,106,111,98,32,105,116,115,101, - 108,102,46,10,10,32,32,32,32,32,32,32,32,122,24,60, - 109,111,100,117,108,101,32,123,33,114,125,32,40,98,117,105, - 108,116,45,105,110,41,62,41,2,114,38,0,0,0,114,1, - 0,0,0,41,1,114,84,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,87,0,0,0,186,2, - 0,0,115,2,0,0,0,0,7,122,27,66,117,105,108,116, - 105,110,73,109,112,111,114,116,101,114,46,109,111,100,117,108, - 101,95,114,101,112,114,78,99,4,0,0,0,0,0,0,0, - 4,0,0,0,5,0,0,0,67,0,0,0,115,44,0,0, - 0,124,2,100,0,107,9,114,12,100,0,83,0,116,0,160, - 1,124,1,161,1,114,36,116,2,124,1,124,0,100,1,100, - 2,141,3,83,0,100,0,83,0,100,0,83,0,41,3,78, - 122,8,98,117,105,108,116,45,105,110,41,1,114,104,0,0, - 0,41,3,114,49,0,0,0,90,10,105,115,95,98,117,105, - 108,116,105,110,114,79,0,0,0,41,4,218,3,99,108,115, - 114,72,0,0,0,218,4,112,97,116,104,218,6,116,97,114, - 103,101,116,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,9,102,105,110,100,95,115,112,101,99,195,2,0, - 0,115,10,0,0,0,0,2,8,1,4,1,10,1,14,2, - 122,25,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 0,0,114,141,0,0,0,177,2,0,0,115,28,0,0,0, + 12,9,12,9,2,1,12,8,2,1,12,11,12,8,12,5, + 2,1,14,5,2,1,14,5,2,1,14,5,114,141,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,4,0, + 0,0,64,0,0,0,115,140,0,0,0,101,0,90,1,100, + 0,90,2,100,1,90,3,101,4,100,2,100,3,132,0,131, + 1,90,5,101,6,100,21,100,5,100,6,132,1,131,1,90, + 7,101,6,100,22,100,7,100,8,132,1,131,1,90,8,101, + 6,100,9,100,10,132,0,131,1,90,9,101,4,100,11,100, + 12,132,0,131,1,90,10,101,6,100,13,100,14,132,0,131, + 1,90,11,101,6,101,12,100,15,100,16,132,0,131,1,131, + 1,90,13,101,6,101,12,100,17,100,18,132,0,131,1,131, + 1,90,14,101,6,101,12,100,19,100,20,132,0,131,1,131, + 1,90,15,100,4,83,0,41,23,218,14,70,114,111,122,101, + 110,73,109,112,111,114,116,101,114,122,142,77,101,116,97,32, + 112,97,116,104,32,105,109,112,111,114,116,32,102,111,114,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,115,46,10, + 10,32,32,32,32,65,108,108,32,109,101,116,104,111,100,115, + 32,97,114,101,32,101,105,116,104,101,114,32,99,108,97,115, + 115,32,111,114,32,115,116,97,116,105,99,32,109,101,116,104, + 111,100,115,32,116,111,32,97,118,111,105,100,32,116,104,101, + 32,110,101,101,100,32,116,111,10,32,32,32,32,105,110,115, + 116,97,110,116,105,97,116,101,32,116,104,101,32,99,108,97, + 115,115,46,10,10,32,32,32,32,99,1,0,0,0,0,0, + 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,12, + 0,0,0,100,1,160,0,124,0,106,1,161,1,83,0,41, + 2,122,115,82,101,116,117,114,110,32,114,101,112,114,32,102, + 111,114,32,116,104,101,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,101,32,109,101,116,104, + 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, + 46,32,32,84,104,101,32,105,109,112,111,114,116,32,109,97, + 99,104,105,110,101,114,121,32,100,111,101,115,32,116,104,101, + 32,106,111,98,32,105,116,115,101,108,102,46,10,10,32,32, + 32,32,32,32,32,32,122,22,60,109,111,100,117,108,101,32, + 123,33,114,125,32,40,102,114,111,122,101,110,41,62,41,2, + 114,38,0,0,0,114,1,0,0,0,41,1,218,1,109,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,86, + 0,0,0,3,3,0,0,115,2,0,0,0,0,7,122,26, + 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,109, + 111,100,117,108,101,95,114,101,112,114,78,99,4,0,0,0, + 0,0,0,0,4,0,0,0,5,0,0,0,67,0,0,0, + 115,32,0,0,0,116,0,160,1,124,1,161,1,114,24,116, + 2,124,1,124,0,100,1,100,2,141,3,83,0,100,0,83, + 0,100,0,83,0,41,3,78,90,6,102,114,111,122,101,110, + 41,1,114,103,0,0,0,41,3,114,49,0,0,0,114,75, + 0,0,0,114,78,0,0,0,41,4,114,142,0,0,0,114, + 71,0,0,0,114,143,0,0,0,114,144,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,145,0, + 0,0,12,3,0,0,115,6,0,0,0,0,2,10,1,14, + 2,122,24,70,114,111,122,101,110,73,109,112,111,114,116,101, 114,46,102,105,110,100,95,115,112,101,99,99,3,0,0,0, - 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, - 115,30,0,0,0,124,0,160,0,124,1,124,2,161,2,125, - 3,124,3,100,1,107,9,114,26,124,3,106,1,83,0,100, - 1,83,0,41,2,122,175,70,105,110,100,32,116,104,101,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,73,102,32,39,112,97, - 116,104,39,32,105,115,32,101,118,101,114,32,115,112,101,99, - 105,102,105,101,100,32,116,104,101,110,32,116,104,101,32,115, - 101,97,114,99,104,32,105,115,32,99,111,110,115,105,100,101, - 114,101,100,32,97,32,102,97,105,108,117,114,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, - 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, - 32,32,32,32,32,32,78,41,2,114,146,0,0,0,114,94, - 0,0,0,41,4,114,143,0,0,0,114,72,0,0,0,114, - 144,0,0,0,114,83,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,11,102,105,110,100,95,109, - 111,100,117,108,101,204,2,0,0,115,4,0,0,0,0,9, - 12,1,122,27,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,46,102,105,110,100,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 67,0,0,0,115,46,0,0,0,124,1,106,0,116,1,106, - 2,107,7,114,34,116,3,100,1,160,4,124,1,106,0,161, - 1,124,1,106,0,100,2,141,2,130,1,116,5,116,6,106, - 7,124,1,131,2,83,0,41,3,122,24,67,114,101,97,116, - 101,32,97,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,122,29,123,33,114,125,32,105,115,32,110,111,116, - 32,97,32,98,117,105,108,116,45,105,110,32,109,111,100,117, - 108,101,41,1,114,15,0,0,0,41,8,114,15,0,0,0, - 114,14,0,0,0,114,70,0,0,0,114,71,0,0,0,114, - 38,0,0,0,114,59,0,0,0,114,49,0,0,0,90,14, - 99,114,101,97,116,101,95,98,117,105,108,116,105,110,41,2, - 114,26,0,0,0,114,83,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,135,0,0,0,216,2, - 0,0,115,8,0,0,0,0,3,12,1,12,1,10,1,122, - 29,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, - 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, - 0,0,0,115,16,0,0,0,116,0,116,1,106,2,124,1, - 131,2,1,0,100,1,83,0,41,2,122,22,69,120,101,99, - 32,97,32,98,117,105,108,116,45,105,110,32,109,111,100,117, - 108,101,78,41,3,114,59,0,0,0,114,49,0,0,0,90, - 12,101,120,101,99,95,98,117,105,108,116,105,110,41,2,114, - 26,0,0,0,114,84,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,136,0,0,0,224,2,0, - 0,115,2,0,0,0,0,3,122,27,66,117,105,108,116,105, + 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, + 115,18,0,0,0,116,0,160,1,124,1,161,1,114,14,124, + 0,83,0,100,1,83,0,41,2,122,93,70,105,110,100,32, + 97,32,102,114,111,122,101,110,32,109,111,100,117,108,101,46, + 10,10,32,32,32,32,32,32,32,32,84,104,105,115,32,109, + 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,46,32,32,85,115,101,32,102,105,110,100,95,115, + 112,101,99,40,41,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,32,32,32,32,78,41,2,114,49,0,0,0, + 114,75,0,0,0,41,3,114,142,0,0,0,114,71,0,0, + 0,114,143,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,146,0,0,0,19,3,0,0,115,2, + 0,0,0,0,7,122,26,70,114,111,122,101,110,73,109,112, + 111,114,116,101,114,46,102,105,110,100,95,109,111,100,117,108, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, + 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, + 2,122,42,85,115,101,32,100,101,102,97,117,108,116,32,115, + 101,109,97,110,116,105,99,115,32,102,111,114,32,109,111,100, + 117,108,101,32,99,114,101,97,116,105,111,110,46,78,114,10, + 0,0,0,41,2,114,142,0,0,0,114,82,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,134, + 0,0,0,28,3,0,0,115,0,0,0,0,122,28,70,114, + 111,122,101,110,73,109,112,111,114,116,101,114,46,99,114,101, + 97,116,101,95,109,111,100,117,108,101,99,1,0,0,0,0, + 0,0,0,3,0,0,0,4,0,0,0,67,0,0,0,115, + 64,0,0,0,124,0,106,0,106,1,125,1,116,2,160,3, + 124,1,161,1,115,36,116,4,100,1,160,5,124,1,161,1, + 124,1,100,2,141,2,130,1,116,6,116,2,106,7,124,1, + 131,2,125,2,116,8,124,2,124,0,106,9,131,2,1,0, + 100,0,83,0,41,3,78,122,27,123,33,114,125,32,105,115, + 32,110,111,116,32,97,32,102,114,111,122,101,110,32,109,111, + 100,117,108,101,41,1,114,15,0,0,0,41,10,114,89,0, + 0,0,114,15,0,0,0,114,49,0,0,0,114,75,0,0, + 0,114,70,0,0,0,114,38,0,0,0,114,59,0,0,0, + 218,17,103,101,116,95,102,114,111,122,101,110,95,111,98,106, + 101,99,116,218,4,101,120,101,99,114,7,0,0,0,41,3, + 114,83,0,0,0,114,15,0,0,0,218,4,99,111,100,101, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 135,0,0,0,32,3,0,0,115,12,0,0,0,0,2,8, + 1,10,1,10,1,8,1,12,1,122,26,70,114,111,122,101, 110,73,109,112,111,114,116,101,114,46,101,120,101,99,95,109, 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, - 1,83,0,41,2,122,57,82,101,116,117,114,110,32,78,111, - 110,101,32,97,115,32,98,117,105,108,116,45,105,110,32,109, - 111,100,117,108,101,115,32,100,111,32,110,111,116,32,104,97, - 118,101,32,99,111,100,101,32,111,98,106,101,99,116,115,46, - 78,114,10,0,0,0,41,2,114,143,0,0,0,114,72,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,8,103,101,116,95,99,111,100,101,229,2,0,0,115, - 2,0,0,0,0,4,122,24,66,117,105,108,116,105,110,73, - 109,112,111,114,116,101,114,46,103,101,116,95,99,111,100,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, - 0,67,0,0,0,115,4,0,0,0,100,1,83,0,41,2, - 122,56,82,101,116,117,114,110,32,78,111,110,101,32,97,115, - 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, - 115,32,100,111,32,110,111,116,32,104,97,118,101,32,115,111, - 117,114,99,101,32,99,111,100,101,46,78,114,10,0,0,0, - 41,2,114,143,0,0,0,114,72,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,218,10,103,101,116, - 95,115,111,117,114,99,101,235,2,0,0,115,2,0,0,0, - 0,4,122,26,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, - 0,0,0,115,4,0,0,0,100,1,83,0,41,2,122,52, - 82,101,116,117,114,110,32,70,97,108,115,101,32,97,115,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,115, - 32,97,114,101,32,110,101,118,101,114,32,112,97,99,107,97, - 103,101,115,46,70,114,10,0,0,0,41,2,114,143,0,0, - 0,114,72,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,106,0,0,0,241,2,0,0,115,2, - 0,0,0,0,4,122,26,66,117,105,108,116,105,110,73,109, - 112,111,114,116,101,114,46,105,115,95,112,97,99,107,97,103, - 101,41,2,78,78,41,1,78,41,17,114,1,0,0,0,114, - 0,0,0,0,114,2,0,0,0,114,3,0,0,0,218,12, - 115,116,97,116,105,99,109,101,116,104,111,100,114,87,0,0, - 0,218,11,99,108,97,115,115,109,101,116,104,111,100,114,146, - 0,0,0,114,147,0,0,0,114,135,0,0,0,114,136,0, - 0,0,114,75,0,0,0,114,148,0,0,0,114,149,0,0, - 0,114,106,0,0,0,114,85,0,0,0,114,138,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,142,0,0,0,177,2,0,0,115,28,0, - 0,0,12,9,12,9,2,1,12,8,2,1,12,11,12,8, - 12,5,2,1,14,5,2,1,14,5,2,1,14,5,114,142, - 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 4,0,0,0,64,0,0,0,115,140,0,0,0,101,0,90, - 1,100,0,90,2,100,1,90,3,101,4,100,2,100,3,132, - 0,131,1,90,5,101,6,100,21,100,5,100,6,132,1,131, - 1,90,7,101,6,100,22,100,7,100,8,132,1,131,1,90, - 8,101,6,100,9,100,10,132,0,131,1,90,9,101,4,100, - 11,100,12,132,0,131,1,90,10,101,6,100,13,100,14,132, - 0,131,1,90,11,101,6,101,12,100,15,100,16,132,0,131, - 1,131,1,90,13,101,6,101,12,100,17,100,18,132,0,131, - 1,131,1,90,14,101,6,101,12,100,19,100,20,132,0,131, - 1,131,1,90,15,100,4,83,0,41,23,218,14,70,114,111, - 122,101,110,73,109,112,111,114,116,101,114,122,142,77,101,116, - 97,32,112,97,116,104,32,105,109,112,111,114,116,32,102,111, - 114,32,102,114,111,122,101,110,32,109,111,100,117,108,101,115, - 46,10,10,32,32,32,32,65,108,108,32,109,101,116,104,111, - 100,115,32,97,114,101,32,101,105,116,104,101,114,32,99,108, - 97,115,115,32,111,114,32,115,116,97,116,105,99,32,109,101, - 116,104,111,100,115,32,116,111,32,97,118,111,105,100,32,116, - 104,101,32,110,101,101,100,32,116,111,10,32,32,32,32,105, - 110,115,116,97,110,116,105,97,116,101,32,116,104,101,32,99, - 108,97,115,115,46,10,10,32,32,32,32,99,1,0,0,0, - 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, - 115,12,0,0,0,100,1,160,0,124,0,106,1,161,1,83, - 0,41,2,122,115,82,101,116,117,114,110,32,114,101,112,114, - 32,102,111,114,32,116,104,101,32,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,84,104,101,32,109,101, - 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, - 101,100,46,32,32,84,104,101,32,105,109,112,111,114,116,32, - 109,97,99,104,105,110,101,114,121,32,100,111,101,115,32,116, - 104,101,32,106,111,98,32,105,116,115,101,108,102,46,10,10, - 32,32,32,32,32,32,32,32,122,22,60,109,111,100,117,108, - 101,32,123,33,114,125,32,40,102,114,111,122,101,110,41,62, - 41,2,114,38,0,0,0,114,1,0,0,0,41,1,218,1, - 109,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,87,0,0,0,3,3,0,0,115,2,0,0,0,0,7, - 122,26,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 46,109,111,100,117,108,101,95,114,101,112,114,78,99,4,0, - 0,0,0,0,0,0,4,0,0,0,5,0,0,0,67,0, - 0,0,115,32,0,0,0,116,0,160,1,124,1,161,1,114, - 24,116,2,124,1,124,0,100,1,100,2,141,3,83,0,100, - 0,83,0,100,0,83,0,41,3,78,90,6,102,114,111,122, - 101,110,41,1,114,104,0,0,0,41,3,114,49,0,0,0, - 114,76,0,0,0,114,79,0,0,0,41,4,114,143,0,0, - 0,114,72,0,0,0,114,144,0,0,0,114,145,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 146,0,0,0,12,3,0,0,115,6,0,0,0,0,2,10, - 1,14,2,122,24,70,114,111,122,101,110,73,109,112,111,114, - 116,101,114,46,102,105,110,100,95,115,112,101,99,99,3,0, - 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, - 0,0,115,18,0,0,0,116,0,160,1,124,1,161,1,114, - 14,124,0,83,0,100,1,83,0,41,2,122,93,70,105,110, + 0,0,3,0,0,0,67,0,0,0,115,10,0,0,0,116, + 0,124,0,124,1,131,2,83,0,41,1,122,95,76,111,97, 100,32,97,32,102,114,111,122,101,110,32,109,111,100,117,108, 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,102,105,110,100, - 95,115,112,101,99,40,41,32,105,110,115,116,101,97,100,46, - 10,10,32,32,32,32,32,32,32,32,78,41,2,114,49,0, - 0,0,114,76,0,0,0,41,3,114,143,0,0,0,114,72, - 0,0,0,114,144,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,147,0,0,0,19,3,0,0, - 115,2,0,0,0,0,7,122,26,70,114,111,122,101,110,73, - 109,112,111,114,116,101,114,46,102,105,110,100,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, - 0,41,2,122,42,85,115,101,32,100,101,102,97,117,108,116, - 32,115,101,109,97,110,116,105,99,115,32,102,111,114,32,109, - 111,100,117,108,101,32,99,114,101,97,116,105,111,110,46,78, - 114,10,0,0,0,41,2,114,143,0,0,0,114,83,0,0, + 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, + 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, + 100,46,10,10,32,32,32,32,32,32,32,32,41,1,114,84, + 0,0,0,41,2,114,142,0,0,0,114,71,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,137, + 0,0,0,41,3,0,0,115,2,0,0,0,0,7,122,26, + 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,108, + 111,97,100,95,109,111,100,117,108,101,99,2,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, + 10,0,0,0,116,0,160,1,124,1,161,1,83,0,41,1, + 122,45,82,101,116,117,114,110,32,116,104,101,32,99,111,100, + 101,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101, + 32,102,114,111,122,101,110,32,109,111,100,117,108,101,46,41, + 2,114,49,0,0,0,114,153,0,0,0,41,2,114,142,0, + 0,0,114,71,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,147,0,0,0,50,3,0,0,115, + 2,0,0,0,0,4,122,23,70,114,111,122,101,110,73,109, + 112,111,114,116,101,114,46,103,101,116,95,99,111,100,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, + 67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,122, + 54,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,115,32,100, + 111,32,110,111,116,32,104,97,118,101,32,115,111,117,114,99, + 101,32,99,111,100,101,46,78,114,10,0,0,0,41,2,114, + 142,0,0,0,114,71,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,148,0,0,0,56,3,0, + 0,115,2,0,0,0,0,4,122,25,70,114,111,122,101,110, + 73,109,112,111,114,116,101,114,46,103,101,116,95,115,111,117, + 114,99,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,67,0,0,0,115,10,0,0,0,116,0,160, + 1,124,1,161,1,83,0,41,1,122,46,82,101,116,117,114, + 110,32,84,114,117,101,32,105,102,32,116,104,101,32,102,114, + 111,122,101,110,32,109,111,100,117,108,101,32,105,115,32,97, + 32,112,97,99,107,97,103,101,46,41,2,114,49,0,0,0, + 90,17,105,115,95,102,114,111,122,101,110,95,112,97,99,107, + 97,103,101,41,2,114,142,0,0,0,114,71,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,105, + 0,0,0,62,3,0,0,115,2,0,0,0,0,4,122,25, + 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,105, + 115,95,112,97,99,107,97,103,101,41,2,78,78,41,1,78, + 41,16,114,1,0,0,0,114,0,0,0,0,114,2,0,0, + 0,114,3,0,0,0,114,149,0,0,0,114,86,0,0,0, + 114,150,0,0,0,114,145,0,0,0,114,146,0,0,0,114, + 134,0,0,0,114,135,0,0,0,114,137,0,0,0,114,77, + 0,0,0,114,147,0,0,0,114,148,0,0,0,114,105,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,151,0,0,0,250,2,0,0,115, + 28,0,0,0,12,9,12,9,2,1,12,6,2,1,12,8, + 12,4,12,9,12,9,2,1,14,5,2,1,14,5,2,1, + 114,151,0,0,0,99,0,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,64,0,0,0,115,32,0,0,0,101, + 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, + 0,90,4,100,4,100,5,132,0,90,5,100,6,83,0,41, + 7,218,18,95,73,109,112,111,114,116,76,111,99,107,67,111, + 110,116,101,120,116,122,36,67,111,110,116,101,120,116,32,109, + 97,110,97,103,101,114,32,102,111,114,32,116,104,101,32,105, + 109,112,111,114,116,32,108,111,99,107,46,99,1,0,0,0, + 0,0,0,0,1,0,0,0,2,0,0,0,67,0,0,0, + 115,12,0,0,0,116,0,160,1,161,0,1,0,100,1,83, + 0,41,2,122,24,65,99,113,117,105,114,101,32,116,104,101, + 32,105,109,112,111,114,116,32,108,111,99,107,46,78,41,2, + 114,49,0,0,0,114,50,0,0,0,41,1,114,26,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,135,0,0,0,28,3,0,0,115,0,0,0,0,122,28, - 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,99, - 114,101,97,116,101,95,109,111,100,117,108,101,99,1,0,0, - 0,0,0,0,0,3,0,0,0,4,0,0,0,67,0,0, - 0,115,64,0,0,0,124,0,106,0,106,1,125,1,116,2, - 160,3,124,1,161,1,115,36,116,4,100,1,160,5,124,1, - 161,1,124,1,100,2,141,2,130,1,116,6,116,2,106,7, - 124,1,131,2,125,2,116,8,124,2,124,0,106,9,131,2, - 1,0,100,0,83,0,41,3,78,122,27,123,33,114,125,32, - 105,115,32,110,111,116,32,97,32,102,114,111,122,101,110,32, - 109,111,100,117,108,101,41,1,114,15,0,0,0,41,10,114, - 90,0,0,0,114,15,0,0,0,114,49,0,0,0,114,76, - 0,0,0,114,71,0,0,0,114,38,0,0,0,114,59,0, - 0,0,218,17,103,101,116,95,102,114,111,122,101,110,95,111, - 98,106,101,99,116,218,4,101,120,101,99,114,7,0,0,0, - 41,3,114,84,0,0,0,114,15,0,0,0,218,4,99,111, - 100,101,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,136,0,0,0,32,3,0,0,115,12,0,0,0,0, - 2,8,1,10,1,10,1,8,1,12,1,122,26,70,114,111, - 122,101,110,73,109,112,111,114,116,101,114,46,101,120,101,99, - 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,115,10,0,0, - 0,116,0,124,0,124,1,131,2,83,0,41,1,122,95,76, - 111,97,100,32,97,32,102,114,111,122,101,110,32,109,111,100, - 117,108,101,46,10,10,32,32,32,32,32,32,32,32,84,104, - 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,46,32,32,85,115,101,32,101,120, - 101,99,95,109,111,100,117,108,101,40,41,32,105,110,115,116, - 101,97,100,46,10,10,32,32,32,32,32,32,32,32,41,1, - 114,85,0,0,0,41,2,114,143,0,0,0,114,72,0,0, + 114,46,0,0,0,75,3,0,0,115,2,0,0,0,0,2, + 122,28,95,73,109,112,111,114,116,76,111,99,107,67,111,110, + 116,101,120,116,46,95,95,101,110,116,101,114,95,95,99,4, + 0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,67, + 0,0,0,115,12,0,0,0,116,0,160,1,161,0,1,0, + 100,1,83,0,41,2,122,60,82,101,108,101,97,115,101,32, + 116,104,101,32,105,109,112,111,114,116,32,108,111,99,107,32, + 114,101,103,97,114,100,108,101,115,115,32,111,102,32,97,110, + 121,32,114,97,105,115,101,100,32,101,120,99,101,112,116,105, + 111,110,115,46,78,41,2,114,49,0,0,0,114,52,0,0, + 0,41,4,114,26,0,0,0,90,8,101,120,99,95,116,121, + 112,101,90,9,101,120,99,95,118,97,108,117,101,90,13,101, + 120,99,95,116,114,97,99,101,98,97,99,107,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,48,0,0,0, + 79,3,0,0,115,2,0,0,0,0,2,122,27,95,73,109, + 112,111,114,116,76,111,99,107,67,111,110,116,101,120,116,46, + 95,95,101,120,105,116,95,95,78,41,6,114,1,0,0,0, + 114,0,0,0,0,114,2,0,0,0,114,3,0,0,0,114, + 46,0,0,0,114,48,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,156,0, + 0,0,71,3,0,0,115,4,0,0,0,12,4,8,4,114, + 156,0,0,0,99,3,0,0,0,0,0,0,0,5,0,0, + 0,5,0,0,0,67,0,0,0,115,64,0,0,0,124,1, + 160,0,100,1,124,2,100,2,24,0,161,2,125,3,116,1, + 124,3,131,1,124,2,107,0,114,36,116,2,100,3,131,1, + 130,1,124,3,100,4,25,0,125,4,124,0,114,60,100,5, + 160,3,124,4,124,0,161,2,83,0,124,4,83,0,41,6, + 122,50,82,101,115,111,108,118,101,32,97,32,114,101,108,97, + 116,105,118,101,32,109,111,100,117,108,101,32,110,97,109,101, + 32,116,111,32,97,110,32,97,98,115,111,108,117,116,101,32, + 111,110,101,46,114,117,0,0,0,114,33,0,0,0,122,50, + 97,116,116,101,109,112,116,101,100,32,114,101,108,97,116,105, + 118,101,32,105,109,112,111,114,116,32,98,101,121,111,110,100, + 32,116,111,112,45,108,101,118,101,108,32,112,97,99,107,97, + 103,101,114,19,0,0,0,122,5,123,125,46,123,125,41,4, + 218,6,114,115,112,108,105,116,218,3,108,101,110,218,10,86, + 97,108,117,101,69,114,114,111,114,114,38,0,0,0,41,5, + 114,15,0,0,0,218,7,112,97,99,107,97,103,101,218,5, + 108,101,118,101,108,90,4,98,105,116,115,90,4,98,97,115, + 101,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,13,95,114,101,115,111,108,118,101,95,110,97,109,101,84, + 3,0,0,115,10,0,0,0,0,2,16,1,12,1,8,1, + 8,1,114,162,0,0,0,99,3,0,0,0,0,0,0,0, + 4,0,0,0,4,0,0,0,67,0,0,0,115,34,0,0, + 0,124,0,160,0,124,1,124,2,161,2,125,3,124,3,100, + 0,107,8,114,24,100,0,83,0,116,1,124,1,124,3,131, + 2,83,0,41,1,78,41,2,114,146,0,0,0,114,78,0, + 0,0,41,4,218,6,102,105,110,100,101,114,114,15,0,0, + 0,114,143,0,0,0,114,93,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,218,17,95,102,105,110, + 100,95,115,112,101,99,95,108,101,103,97,99,121,93,3,0, + 0,115,8,0,0,0,0,3,12,1,8,1,4,1,114,164, + 0,0,0,99,3,0,0,0,0,0,0,0,10,0,0,0, + 27,0,0,0,67,0,0,0,115,240,0,0,0,116,0,106, + 1,125,3,124,3,100,1,107,8,114,22,116,2,100,2,131, + 1,130,1,124,3,115,38,116,3,160,4,100,3,116,5,161, + 2,1,0,124,0,116,0,106,6,107,6,125,4,120,186,124, + 3,68,0,93,174,125,5,116,7,131,0,143,72,1,0,121, + 10,124,5,106,8,125,6,87,0,110,42,4,0,116,9,107, + 10,114,118,1,0,1,0,1,0,116,10,124,5,124,0,124, + 1,131,3,125,7,124,7,100,1,107,8,114,114,119,54,89, + 0,110,14,88,0,124,6,124,0,124,1,124,2,131,3,125, + 7,87,0,100,1,81,0,82,0,88,0,124,7,100,1,107, + 9,114,54,124,4,115,224,124,0,116,0,106,6,107,6,114, + 224,116,0,106,6,124,0,25,0,125,8,121,10,124,8,106, + 11,125,9,87,0,110,20,4,0,116,9,107,10,114,204,1, + 0,1,0,1,0,124,7,83,0,88,0,124,9,100,1,107, + 8,114,218,124,7,83,0,124,9,83,0,113,54,124,7,83, + 0,113,54,87,0,100,1,83,0,100,1,83,0,41,4,122, + 21,70,105,110,100,32,97,32,109,111,100,117,108,101,39,115, + 32,115,112,101,99,46,78,122,53,115,121,115,46,109,101,116, + 97,95,112,97,116,104,32,105,115,32,78,111,110,101,44,32, + 80,121,116,104,111,110,32,105,115,32,108,105,107,101,108,121, + 32,115,104,117,116,116,105,110,103,32,100,111,119,110,122,22, + 115,121,115,46,109,101,116,97,95,112,97,116,104,32,105,115, + 32,101,109,112,116,121,41,12,114,14,0,0,0,218,9,109, + 101,116,97,95,112,97,116,104,114,70,0,0,0,218,9,95, + 119,97,114,110,105,110,103,115,218,4,119,97,114,110,218,13, + 73,109,112,111,114,116,87,97,114,110,105,110,103,114,79,0, + 0,0,114,156,0,0,0,114,145,0,0,0,114,90,0,0, + 0,114,164,0,0,0,114,89,0,0,0,41,10,114,15,0, + 0,0,114,143,0,0,0,114,144,0,0,0,114,165,0,0, + 0,90,9,105,115,95,114,101,108,111,97,100,114,163,0,0, + 0,114,145,0,0,0,114,82,0,0,0,114,83,0,0,0, + 114,89,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,10,95,102,105,110,100,95,115,112,101,99, + 102,3,0,0,115,54,0,0,0,0,2,6,1,8,2,8, + 3,4,1,12,5,10,1,10,1,8,1,2,1,10,1,14, + 1,12,1,8,1,8,2,22,1,8,2,14,1,10,1,2, + 1,10,1,14,4,6,2,8,1,4,2,6,2,8,2,114, + 169,0,0,0,99,3,0,0,0,0,0,0,0,3,0,0, + 0,5,0,0,0,67,0,0,0,115,108,0,0,0,116,0, + 124,0,116,1,131,2,115,28,116,2,100,1,160,3,116,4, + 124,0,131,1,161,1,131,1,130,1,124,2,100,2,107,0, + 114,44,116,5,100,3,131,1,130,1,124,2,100,2,107,4, + 114,84,116,0,124,1,116,1,131,2,115,72,116,2,100,4, + 131,1,130,1,110,12,124,1,115,84,116,6,100,5,131,1, + 130,1,124,0,115,104,124,2,100,2,107,2,114,104,116,5, + 100,6,131,1,130,1,100,7,83,0,41,8,122,28,86,101, + 114,105,102,121,32,97,114,103,117,109,101,110,116,115,32,97, + 114,101,32,34,115,97,110,101,34,46,122,31,109,111,100,117, + 108,101,32,110,97,109,101,32,109,117,115,116,32,98,101,32, + 115,116,114,44,32,110,111,116,32,123,125,114,19,0,0,0, + 122,18,108,101,118,101,108,32,109,117,115,116,32,98,101,32, + 62,61,32,48,122,31,95,95,112,97,99,107,97,103,101,95, + 95,32,110,111,116,32,115,101,116,32,116,111,32,97,32,115, + 116,114,105,110,103,122,54,97,116,116,101,109,112,116,101,100, + 32,114,101,108,97,116,105,118,101,32,105,109,112,111,114,116, + 32,119,105,116,104,32,110,111,32,107,110,111,119,110,32,112, + 97,114,101,110,116,32,112,97,99,107,97,103,101,122,17,69, + 109,112,116,121,32,109,111,100,117,108,101,32,110,97,109,101, + 78,41,7,218,10,105,115,105,110,115,116,97,110,99,101,218, + 3,115,116,114,218,9,84,121,112,101,69,114,114,111,114,114, + 38,0,0,0,114,13,0,0,0,114,159,0,0,0,114,70, + 0,0,0,41,3,114,15,0,0,0,114,160,0,0,0,114, + 161,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,13,95,115,97,110,105,116,121,95,99,104,101, + 99,107,149,3,0,0,115,22,0,0,0,0,2,10,1,18, + 1,8,1,8,1,8,1,10,1,10,1,4,1,8,2,12, + 1,114,173,0,0,0,122,16,78,111,32,109,111,100,117,108, + 101,32,110,97,109,101,100,32,122,4,123,33,114,125,99,2, + 0,0,0,0,0,0,0,8,0,0,0,13,0,0,0,67, + 0,0,0,115,220,0,0,0,100,0,125,2,124,0,160,0, + 100,1,161,1,100,2,25,0,125,3,124,3,114,134,124,3, + 116,1,106,2,107,7,114,42,116,3,124,1,124,3,131,2, + 1,0,124,0,116,1,106,2,107,6,114,62,116,1,106,2, + 124,0,25,0,83,0,116,1,106,2,124,3,25,0,125,4, + 121,10,124,4,106,4,125,2,87,0,110,50,4,0,116,5, + 107,10,114,132,1,0,1,0,1,0,116,6,100,3,23,0, + 160,7,124,0,124,3,161,2,125,5,116,8,124,5,124,0, + 100,4,141,2,100,0,130,2,89,0,110,2,88,0,116,9, + 124,0,124,2,131,2,125,6,124,6,100,0,107,8,114,172, + 116,8,116,6,160,7,124,0,161,1,124,0,100,4,141,2, + 130,1,110,8,116,10,124,6,131,1,125,7,124,3,114,216, + 116,1,106,2,124,3,25,0,125,4,116,11,124,4,124,0, + 160,0,100,1,161,1,100,5,25,0,124,7,131,3,1,0, + 124,7,83,0,41,6,78,114,117,0,0,0,114,19,0,0, + 0,122,23,59,32,123,33,114,125,32,105,115,32,110,111,116, + 32,97,32,112,97,99,107,97,103,101,41,1,114,15,0,0, + 0,233,2,0,0,0,41,12,114,118,0,0,0,114,14,0, + 0,0,114,79,0,0,0,114,59,0,0,0,114,127,0,0, + 0,114,90,0,0,0,218,8,95,69,82,82,95,77,83,71, + 114,38,0,0,0,218,19,77,111,100,117,108,101,78,111,116, + 70,111,117,110,100,69,114,114,111,114,114,169,0,0,0,114, + 140,0,0,0,114,5,0,0,0,41,8,114,15,0,0,0, + 218,7,105,109,112,111,114,116,95,114,143,0,0,0,114,119, + 0,0,0,90,13,112,97,114,101,110,116,95,109,111,100,117, + 108,101,114,138,0,0,0,114,82,0,0,0,114,83,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,138,0,0,0,41,3,0,0,115,2,0,0,0,0,7, - 122,26,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, - 0,115,10,0,0,0,116,0,160,1,124,1,161,1,83,0, - 41,1,122,45,82,101,116,117,114,110,32,116,104,101,32,99, - 111,100,101,32,111,98,106,101,99,116,32,102,111,114,32,116, - 104,101,32,102,114,111,122,101,110,32,109,111,100,117,108,101, - 46,41,2,114,49,0,0,0,114,154,0,0,0,41,2,114, - 143,0,0,0,114,72,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,148,0,0,0,50,3,0, - 0,115,2,0,0,0,0,4,122,23,70,114,111,122,101,110, - 73,109,112,111,114,116,101,114,46,103,101,116,95,99,111,100, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,122,54,82,101,116,117,114,110,32,78,111,110,101,32,97, - 115,32,102,114,111,122,101,110,32,109,111,100,117,108,101,115, - 32,100,111,32,110,111,116,32,104,97,118,101,32,115,111,117, - 114,99,101,32,99,111,100,101,46,78,114,10,0,0,0,41, - 2,114,143,0,0,0,114,72,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,149,0,0,0,56, - 3,0,0,115,2,0,0,0,0,4,122,25,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,46,103,101,116,95,115, - 111,117,114,99,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,3,0,0,0,67,0,0,0,115,10,0,0,0,116, - 0,160,1,124,1,161,1,83,0,41,1,122,46,82,101,116, - 117,114,110,32,84,114,117,101,32,105,102,32,116,104,101,32, - 102,114,111,122,101,110,32,109,111,100,117,108,101,32,105,115, - 32,97,32,112,97,99,107,97,103,101,46,41,2,114,49,0, - 0,0,90,17,105,115,95,102,114,111,122,101,110,95,112,97, - 99,107,97,103,101,41,2,114,143,0,0,0,114,72,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,106,0,0,0,62,3,0,0,115,2,0,0,0,0,4, - 122,25,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 46,105,115,95,112,97,99,107,97,103,101,41,2,78,78,41, - 1,78,41,16,114,1,0,0,0,114,0,0,0,0,114,2, - 0,0,0,114,3,0,0,0,114,150,0,0,0,114,87,0, - 0,0,114,151,0,0,0,114,146,0,0,0,114,147,0,0, - 0,114,135,0,0,0,114,136,0,0,0,114,138,0,0,0, - 114,78,0,0,0,114,148,0,0,0,114,149,0,0,0,114, - 106,0,0,0,114,10,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,152,0,0,0,250,2,0, - 0,115,28,0,0,0,12,9,12,9,2,1,12,6,2,1, - 12,8,12,4,12,9,12,9,2,1,14,5,2,1,14,5, - 2,1,114,152,0,0,0,99,0,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,64,0,0,0,115,32,0,0, - 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, - 3,132,0,90,4,100,4,100,5,132,0,90,5,100,6,83, - 0,41,7,218,18,95,73,109,112,111,114,116,76,111,99,107, - 67,111,110,116,101,120,116,122,36,67,111,110,116,101,120,116, - 32,109,97,110,97,103,101,114,32,102,111,114,32,116,104,101, - 32,105,109,112,111,114,116,32,108,111,99,107,46,99,1,0, - 0,0,0,0,0,0,1,0,0,0,2,0,0,0,67,0, - 0,0,115,12,0,0,0,116,0,160,1,161,0,1,0,100, - 1,83,0,41,2,122,24,65,99,113,117,105,114,101,32,116, - 104,101,32,105,109,112,111,114,116,32,108,111,99,107,46,78, - 41,2,114,49,0,0,0,114,50,0,0,0,41,1,114,26, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,46,0,0,0,75,3,0,0,115,2,0,0,0, - 0,2,122,28,95,73,109,112,111,114,116,76,111,99,107,67, - 111,110,116,101,120,116,46,95,95,101,110,116,101,114,95,95, - 99,4,0,0,0,0,0,0,0,4,0,0,0,2,0,0, - 0,67,0,0,0,115,12,0,0,0,116,0,160,1,161,0, - 1,0,100,1,83,0,41,2,122,60,82,101,108,101,97,115, - 101,32,116,104,101,32,105,109,112,111,114,116,32,108,111,99, - 107,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32, - 97,110,121,32,114,97,105,115,101,100,32,101,120,99,101,112, - 116,105,111,110,115,46,78,41,2,114,49,0,0,0,114,52, - 0,0,0,41,4,114,26,0,0,0,90,8,101,120,99,95, - 116,121,112,101,90,9,101,120,99,95,118,97,108,117,101,90, - 13,101,120,99,95,116,114,97,99,101,98,97,99,107,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,48,0, - 0,0,79,3,0,0,115,2,0,0,0,0,2,122,27,95, - 73,109,112,111,114,116,76,111,99,107,67,111,110,116,101,120, - 116,46,95,95,101,120,105,116,95,95,78,41,6,114,1,0, - 0,0,114,0,0,0,0,114,2,0,0,0,114,3,0,0, - 0,114,46,0,0,0,114,48,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 157,0,0,0,71,3,0,0,115,4,0,0,0,12,4,8, - 4,114,157,0,0,0,99,3,0,0,0,0,0,0,0,5, - 0,0,0,5,0,0,0,67,0,0,0,115,64,0,0,0, - 124,1,160,0,100,1,124,2,100,2,24,0,161,2,125,3, - 116,1,124,3,131,1,124,2,107,0,114,36,116,2,100,3, - 131,1,130,1,124,3,100,4,25,0,125,4,124,0,114,60, - 100,5,160,3,124,4,124,0,161,2,83,0,124,4,83,0, - 41,6,122,50,82,101,115,111,108,118,101,32,97,32,114,101, - 108,97,116,105,118,101,32,109,111,100,117,108,101,32,110,97, - 109,101,32,116,111,32,97,110,32,97,98,115,111,108,117,116, - 101,32,111,110,101,46,114,118,0,0,0,114,33,0,0,0, - 122,50,97,116,116,101,109,112,116,101,100,32,114,101,108,97, - 116,105,118,101,32,105,109,112,111,114,116,32,98,101,121,111, - 110,100,32,116,111,112,45,108,101,118,101,108,32,112,97,99, - 107,97,103,101,114,19,0,0,0,122,5,123,125,46,123,125, - 41,4,218,6,114,115,112,108,105,116,218,3,108,101,110,218, - 10,86,97,108,117,101,69,114,114,111,114,114,38,0,0,0, - 41,5,114,15,0,0,0,218,7,112,97,99,107,97,103,101, - 218,5,108,101,118,101,108,90,4,98,105,116,115,90,4,98, - 97,115,101,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,13,95,114,101,115,111,108,118,101,95,110,97,109, - 101,84,3,0,0,115,10,0,0,0,0,2,16,1,12,1, - 8,1,8,1,114,163,0,0,0,99,3,0,0,0,0,0, - 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,34, - 0,0,0,124,0,160,0,124,1,124,2,161,2,125,3,124, - 3,100,0,107,8,114,24,100,0,83,0,116,1,124,1,124, - 3,131,2,83,0,41,1,78,41,2,114,147,0,0,0,114, - 79,0,0,0,41,4,218,6,102,105,110,100,101,114,114,15, - 0,0,0,114,144,0,0,0,114,94,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,218,17,95,102, - 105,110,100,95,115,112,101,99,95,108,101,103,97,99,121,93, - 3,0,0,115,8,0,0,0,0,3,12,1,8,1,4,1, - 114,165,0,0,0,99,3,0,0,0,0,0,0,0,10,0, - 0,0,27,0,0,0,67,0,0,0,115,240,0,0,0,116, - 0,106,1,125,3,124,3,100,1,107,8,114,22,116,2,100, - 2,131,1,130,1,124,3,115,38,116,3,160,4,100,3,116, - 5,161,2,1,0,124,0,116,0,106,6,107,6,125,4,120, - 186,124,3,68,0,93,174,125,5,116,7,131,0,143,72,1, - 0,121,10,124,5,106,8,125,6,87,0,110,42,4,0,116, - 9,107,10,114,118,1,0,1,0,1,0,116,10,124,5,124, - 0,124,1,131,3,125,7,124,7,100,1,107,8,114,114,119, - 54,89,0,110,14,88,0,124,6,124,0,124,1,124,2,131, - 3,125,7,87,0,100,1,81,0,82,0,88,0,124,7,100, - 1,107,9,114,54,124,4,115,224,124,0,116,0,106,6,107, - 6,114,224,116,0,106,6,124,0,25,0,125,8,121,10,124, - 8,106,11,125,9,87,0,110,20,4,0,116,9,107,10,114, - 204,1,0,1,0,1,0,124,7,83,0,88,0,124,9,100, - 1,107,8,114,218,124,7,83,0,124,9,83,0,113,54,124, - 7,83,0,113,54,87,0,100,1,83,0,100,1,83,0,41, - 4,122,21,70,105,110,100,32,97,32,109,111,100,117,108,101, - 39,115,32,115,112,101,99,46,78,122,53,115,121,115,46,109, - 101,116,97,95,112,97,116,104,32,105,115,32,78,111,110,101, - 44,32,80,121,116,104,111,110,32,105,115,32,108,105,107,101, - 108,121,32,115,104,117,116,116,105,110,103,32,100,111,119,110, - 122,22,115,121,115,46,109,101,116,97,95,112,97,116,104,32, - 105,115,32,101,109,112,116,121,41,12,114,14,0,0,0,218, - 9,109,101,116,97,95,112,97,116,104,114,71,0,0,0,218, - 9,95,119,97,114,110,105,110,103,115,218,4,119,97,114,110, - 218,13,73,109,112,111,114,116,87,97,114,110,105,110,103,114, - 80,0,0,0,114,157,0,0,0,114,146,0,0,0,114,91, - 0,0,0,114,165,0,0,0,114,90,0,0,0,41,10,114, - 15,0,0,0,114,144,0,0,0,114,145,0,0,0,114,166, - 0,0,0,90,9,105,115,95,114,101,108,111,97,100,114,164, - 0,0,0,114,146,0,0,0,114,83,0,0,0,114,84,0, - 0,0,114,90,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,10,95,102,105,110,100,95,115,112, - 101,99,102,3,0,0,115,54,0,0,0,0,2,6,1,8, - 2,8,3,4,1,12,5,10,1,10,1,8,1,2,1,10, - 1,14,1,12,1,8,1,8,2,22,1,8,2,14,1,10, - 1,2,1,10,1,14,4,6,2,8,1,4,2,6,2,8, - 2,114,170,0,0,0,99,3,0,0,0,0,0,0,0,3, - 0,0,0,5,0,0,0,67,0,0,0,115,108,0,0,0, - 116,0,124,0,116,1,131,2,115,28,116,2,100,1,160,3, - 116,4,124,0,131,1,161,1,131,1,130,1,124,2,100,2, - 107,0,114,44,116,5,100,3,131,1,130,1,124,2,100,2, - 107,4,114,84,116,0,124,1,116,1,131,2,115,72,116,2, - 100,4,131,1,130,1,110,12,124,1,115,84,116,6,100,5, - 131,1,130,1,124,0,115,104,124,2,100,2,107,2,114,104, - 116,5,100,6,131,1,130,1,100,7,83,0,41,8,122,28, - 86,101,114,105,102,121,32,97,114,103,117,109,101,110,116,115, - 32,97,114,101,32,34,115,97,110,101,34,46,122,31,109,111, - 100,117,108,101,32,110,97,109,101,32,109,117,115,116,32,98, - 101,32,115,116,114,44,32,110,111,116,32,123,125,114,19,0, - 0,0,122,18,108,101,118,101,108,32,109,117,115,116,32,98, - 101,32,62,61,32,48,122,31,95,95,112,97,99,107,97,103, - 101,95,95,32,110,111,116,32,115,101,116,32,116,111,32,97, - 32,115,116,114,105,110,103,122,54,97,116,116,101,109,112,116, - 101,100,32,114,101,108,97,116,105,118,101,32,105,109,112,111, - 114,116,32,119,105,116,104,32,110,111,32,107,110,111,119,110, - 32,112,97,114,101,110,116,32,112,97,99,107,97,103,101,122, - 17,69,109,112,116,121,32,109,111,100,117,108,101,32,110,97, - 109,101,78,41,7,218,10,105,115,105,110,115,116,97,110,99, - 101,218,3,115,116,114,218,9,84,121,112,101,69,114,114,111, - 114,114,38,0,0,0,114,13,0,0,0,114,160,0,0,0, - 114,71,0,0,0,41,3,114,15,0,0,0,114,161,0,0, - 0,114,162,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,218,13,95,115,97,110,105,116,121,95,99, - 104,101,99,107,149,3,0,0,115,22,0,0,0,0,2,10, - 1,18,1,8,1,8,1,8,1,10,1,10,1,4,1,8, - 2,12,1,114,174,0,0,0,122,16,78,111,32,109,111,100, - 117,108,101,32,110,97,109,101,100,32,122,4,123,33,114,125, - 99,2,0,0,0,0,0,0,0,8,0,0,0,13,0,0, - 0,67,0,0,0,115,220,0,0,0,100,0,125,2,124,0, - 160,0,100,1,161,1,100,2,25,0,125,3,124,3,114,134, - 124,3,116,1,106,2,107,7,114,42,116,3,124,1,124,3, - 131,2,1,0,124,0,116,1,106,2,107,6,114,62,116,1, - 106,2,124,0,25,0,83,0,116,1,106,2,124,3,25,0, - 125,4,121,10,124,4,106,4,125,2,87,0,110,50,4,0, - 116,5,107,10,114,132,1,0,1,0,1,0,116,6,100,3, - 23,0,160,7,124,0,124,3,161,2,125,5,116,8,124,5, - 124,0,100,4,141,2,100,0,130,2,89,0,110,2,88,0, - 116,9,124,0,124,2,131,2,125,6,124,6,100,0,107,8, - 114,172,116,8,116,6,160,7,124,0,161,1,124,0,100,4, - 141,2,130,1,110,8,116,10,124,6,131,1,125,7,124,3, - 114,216,116,1,106,2,124,3,25,0,125,4,116,11,124,4, - 124,0,160,0,100,1,161,1,100,5,25,0,124,7,131,3, - 1,0,124,7,83,0,41,6,78,114,118,0,0,0,114,19, - 0,0,0,122,23,59,32,123,33,114,125,32,105,115,32,110, - 111,116,32,97,32,112,97,99,107,97,103,101,41,1,114,15, - 0,0,0,233,2,0,0,0,41,12,114,119,0,0,0,114, - 14,0,0,0,114,80,0,0,0,114,59,0,0,0,114,128, - 0,0,0,114,91,0,0,0,218,8,95,69,82,82,95,77, - 83,71,114,38,0,0,0,218,19,77,111,100,117,108,101,78, - 111,116,70,111,117,110,100,69,114,114,111,114,114,170,0,0, - 0,114,141,0,0,0,114,5,0,0,0,41,8,114,15,0, - 0,0,218,7,105,109,112,111,114,116,95,114,144,0,0,0, - 114,120,0,0,0,90,13,112,97,114,101,110,116,95,109,111, - 100,117,108,101,114,139,0,0,0,114,83,0,0,0,114,84, + 218,23,95,102,105,110,100,95,97,110,100,95,108,111,97,100, + 95,117,110,108,111,99,107,101,100,168,3,0,0,115,42,0, + 0,0,0,1,4,1,14,1,4,1,10,1,10,2,10,1, + 10,1,10,1,2,1,10,1,14,1,16,1,20,1,10,1, + 8,1,20,2,8,1,4,2,10,1,22,1,114,178,0,0, + 0,99,2,0,0,0,0,0,0,0,4,0,0,0,11,0, + 0,0,67,0,0,0,115,94,0,0,0,116,0,124,0,131, + 1,143,38,1,0,116,1,106,2,160,3,124,0,116,4,161, + 2,125,2,124,2,116,4,107,8,114,42,116,5,124,0,124, + 1,131,2,83,0,87,0,100,1,81,0,82,0,88,0,124, + 2,100,1,107,8,114,82,100,2,160,6,124,0,161,1,125, + 3,116,7,124,3,124,0,100,3,141,2,130,1,116,8,124, + 0,131,1,1,0,124,2,83,0,41,4,122,25,70,105,110, + 100,32,97,110,100,32,108,111,97,100,32,116,104,101,32,109, + 111,100,117,108,101,46,78,122,40,105,109,112,111,114,116,32, + 111,102,32,123,125,32,104,97,108,116,101,100,59,32,78,111, + 110,101,32,105,110,32,115,121,115,46,109,111,100,117,108,101, + 115,41,1,114,15,0,0,0,41,9,114,42,0,0,0,114, + 14,0,0,0,114,79,0,0,0,114,30,0,0,0,218,14, + 95,78,69,69,68,83,95,76,79,65,68,73,78,71,114,178, + 0,0,0,114,38,0,0,0,114,176,0,0,0,114,57,0, + 0,0,41,4,114,15,0,0,0,114,177,0,0,0,114,83, + 0,0,0,114,67,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,14,95,102,105,110,100,95,97, + 110,100,95,108,111,97,100,198,3,0,0,115,20,0,0,0, + 0,2,10,1,14,1,8,1,20,2,8,1,4,1,6,1, + 12,2,8,1,114,180,0,0,0,114,19,0,0,0,99,3, + 0,0,0,0,0,0,0,3,0,0,0,4,0,0,0,67, + 0,0,0,115,42,0,0,0,116,0,124,0,124,1,124,2, + 131,3,1,0,124,2,100,1,107,4,114,32,116,1,124,0, + 124,1,124,2,131,3,125,0,116,2,124,0,116,3,131,2, + 83,0,41,2,97,50,1,0,0,73,109,112,111,114,116,32, + 97,110,100,32,114,101,116,117,114,110,32,116,104,101,32,109, + 111,100,117,108,101,32,98,97,115,101,100,32,111,110,32,105, + 116,115,32,110,97,109,101,44,32,116,104,101,32,112,97,99, + 107,97,103,101,32,116,104,101,32,99,97,108,108,32,105,115, + 10,32,32,32,32,98,101,105,110,103,32,109,97,100,101,32, + 102,114,111,109,44,32,97,110,100,32,116,104,101,32,108,101, + 118,101,108,32,97,100,106,117,115,116,109,101,110,116,46,10, + 10,32,32,32,32,84,104,105,115,32,102,117,110,99,116,105, + 111,110,32,114,101,112,114,101,115,101,110,116,115,32,116,104, + 101,32,103,114,101,97,116,101,115,116,32,99,111,109,109,111, + 110,32,100,101,110,111,109,105,110,97,116,111,114,32,111,102, + 32,102,117,110,99,116,105,111,110,97,108,105,116,121,10,32, + 32,32,32,98,101,116,119,101,101,110,32,105,109,112,111,114, + 116,95,109,111,100,117,108,101,32,97,110,100,32,95,95,105, + 109,112,111,114,116,95,95,46,32,84,104,105,115,32,105,110, + 99,108,117,100,101,115,32,115,101,116,116,105,110,103,32,95, + 95,112,97,99,107,97,103,101,95,95,32,105,102,10,32,32, + 32,32,116,104,101,32,108,111,97,100,101,114,32,100,105,100, + 32,110,111,116,46,10,10,32,32,32,32,114,19,0,0,0, + 41,4,114,173,0,0,0,114,162,0,0,0,114,180,0,0, + 0,218,11,95,103,99,100,95,105,109,112,111,114,116,41,3, + 114,15,0,0,0,114,160,0,0,0,114,161,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,181, + 0,0,0,214,3,0,0,115,8,0,0,0,0,9,12,1, + 8,1,12,1,114,181,0,0,0,41,1,218,9,114,101,99, + 117,114,115,105,118,101,99,3,0,0,0,1,0,0,0,8, + 0,0,0,17,0,0,0,67,0,0,0,115,234,0,0,0, + 116,0,124,0,100,1,131,2,114,230,120,218,124,1,68,0, + 93,210,125,4,116,1,124,4,116,2,131,2,115,78,124,3, + 114,46,124,0,106,3,100,2,23,0,125,5,110,4,100,3, + 125,5,116,4,100,4,124,5,155,0,100,5,116,5,124,4, + 131,1,106,3,155,0,157,4,131,1,130,1,113,16,124,4, + 100,6,107,2,114,120,124,3,115,226,116,0,124,0,100,7, + 131,2,114,226,116,6,124,0,124,0,106,7,124,2,100,8, + 100,9,141,4,1,0,113,16,116,0,124,0,124,4,131,2, + 115,16,100,10,160,8,124,0,106,3,124,4,161,2,125,6, + 121,14,116,9,124,2,124,6,131,2,1,0,87,0,113,16, + 4,0,116,10,107,10,114,224,1,0,125,7,1,0,122,38, + 124,7,106,11,124,6,107,2,114,206,116,12,106,13,160,14, + 124,6,116,15,161,2,100,11,107,9,114,206,119,16,130,0, + 87,0,89,0,100,11,100,11,125,7,126,7,88,0,113,16, + 88,0,113,16,87,0,124,0,83,0,41,12,122,238,70,105, + 103,117,114,101,32,111,117,116,32,119,104,97,116,32,95,95, + 105,109,112,111,114,116,95,95,32,115,104,111,117,108,100,32, + 114,101,116,117,114,110,46,10,10,32,32,32,32,84,104,101, + 32,105,109,112,111,114,116,95,32,112,97,114,97,109,101,116, + 101,114,32,105,115,32,97,32,99,97,108,108,97,98,108,101, + 32,119,104,105,99,104,32,116,97,107,101,115,32,116,104,101, + 32,110,97,109,101,32,111,102,32,109,111,100,117,108,101,32, + 116,111,10,32,32,32,32,105,109,112,111,114,116,46,32,73, + 116,32,105,115,32,114,101,113,117,105,114,101,100,32,116,111, + 32,100,101,99,111,117,112,108,101,32,116,104,101,32,102,117, + 110,99,116,105,111,110,32,102,114,111,109,32,97,115,115,117, + 109,105,110,103,32,105,109,112,111,114,116,108,105,98,39,115, + 10,32,32,32,32,105,109,112,111,114,116,32,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,32,105,115,32,100,101, + 115,105,114,101,100,46,10,10,32,32,32,32,114,127,0,0, + 0,122,8,46,95,95,97,108,108,95,95,122,13,96,96,102, + 114,111,109,32,108,105,115,116,39,39,122,8,73,116,101,109, + 32,105,110,32,122,18,32,109,117,115,116,32,98,101,32,115, + 116,114,44,32,110,111,116,32,250,1,42,218,7,95,95,97, + 108,108,95,95,84,41,1,114,182,0,0,0,122,5,123,125, + 46,123,125,78,41,16,114,4,0,0,0,114,170,0,0,0, + 114,171,0,0,0,114,1,0,0,0,114,172,0,0,0,114, + 13,0,0,0,218,16,95,104,97,110,100,108,101,95,102,114, + 111,109,108,105,115,116,114,184,0,0,0,114,38,0,0,0, + 114,59,0,0,0,114,176,0,0,0,114,15,0,0,0,114, + 14,0,0,0,114,79,0,0,0,114,30,0,0,0,114,179, + 0,0,0,41,8,114,83,0,0,0,218,8,102,114,111,109, + 108,105,115,116,114,177,0,0,0,114,182,0,0,0,218,1, + 120,90,5,119,104,101,114,101,90,9,102,114,111,109,95,110, + 97,109,101,90,3,101,120,99,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,185,0,0,0,229,3,0,0, + 115,42,0,0,0,0,10,10,1,10,1,10,1,4,1,12, + 2,4,1,28,2,8,1,14,1,10,1,10,1,10,1,14, + 1,2,1,14,1,16,4,10,1,18,1,2,1,24,1,114, + 185,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0, + 0,6,0,0,0,67,0,0,0,115,146,0,0,0,124,0, + 160,0,100,1,161,1,125,1,124,0,160,0,100,2,161,1, + 125,2,124,1,100,3,107,9,114,82,124,2,100,3,107,9, + 114,78,124,1,124,2,106,1,107,3,114,78,116,2,106,3, + 100,4,124,1,155,2,100,5,124,2,106,1,155,2,100,6, + 157,5,116,4,100,7,100,8,141,3,1,0,124,1,83,0, + 124,2,100,3,107,9,114,96,124,2,106,1,83,0,116,2, + 106,3,100,9,116,4,100,7,100,8,141,3,1,0,124,0, + 100,10,25,0,125,1,100,11,124,0,107,7,114,142,124,1, + 160,5,100,12,161,1,100,13,25,0,125,1,124,1,83,0, + 41,14,122,167,67,97,108,99,117,108,97,116,101,32,119,104, + 97,116,32,95,95,112,97,99,107,97,103,101,95,95,32,115, + 104,111,117,108,100,32,98,101,46,10,10,32,32,32,32,95, + 95,112,97,99,107,97,103,101,95,95,32,105,115,32,110,111, + 116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32, + 98,101,32,100,101,102,105,110,101,100,32,111,114,32,99,111, + 117,108,100,32,98,101,32,115,101,116,32,116,111,32,78,111, + 110,101,10,32,32,32,32,116,111,32,114,101,112,114,101,115, + 101,110,116,32,116,104,97,116,32,105,116,115,32,112,114,111, + 112,101,114,32,118,97,108,117,101,32,105,115,32,117,110,107, + 110,111,119,110,46,10,10,32,32,32,32,114,130,0,0,0, + 114,89,0,0,0,78,122,32,95,95,112,97,99,107,97,103, + 101,95,95,32,33,61,32,95,95,115,112,101,99,95,95,46, + 112,97,114,101,110,116,32,40,122,4,32,33,61,32,250,1, + 41,233,3,0,0,0,41,1,90,10,115,116,97,99,107,108, + 101,118,101,108,122,89,99,97,110,39,116,32,114,101,115,111, + 108,118,101,32,112,97,99,107,97,103,101,32,102,114,111,109, + 32,95,95,115,112,101,99,95,95,32,111,114,32,95,95,112, + 97,99,107,97,103,101,95,95,44,32,102,97,108,108,105,110, + 103,32,98,97,99,107,32,111,110,32,95,95,110,97,109,101, + 95,95,32,97,110,100,32,95,95,112,97,116,104,95,95,114, + 1,0,0,0,114,127,0,0,0,114,117,0,0,0,114,19, + 0,0,0,41,6,114,30,0,0,0,114,119,0,0,0,114, + 166,0,0,0,114,167,0,0,0,114,168,0,0,0,114,118, + 0,0,0,41,3,218,7,103,108,111,98,97,108,115,114,160, + 0,0,0,114,82,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,17,95,99,97,108,99,95,95, + 95,112,97,99,107,97,103,101,95,95,11,4,0,0,115,30, + 0,0,0,0,7,10,1,10,1,8,1,18,1,22,2,10, + 1,4,1,8,1,6,2,6,2,10,1,8,1,8,1,14, + 1,114,191,0,0,0,114,10,0,0,0,99,5,0,0,0, + 0,0,0,0,9,0,0,0,5,0,0,0,67,0,0,0, + 115,166,0,0,0,124,4,100,1,107,2,114,18,116,0,124, + 0,131,1,125,5,110,36,124,1,100,2,107,9,114,30,124, + 1,110,2,105,0,125,6,116,1,124,6,131,1,125,7,116, + 0,124,0,124,7,124,4,131,3,125,5,124,3,115,150,124, + 4,100,1,107,2,114,84,116,0,124,0,160,2,100,3,161, + 1,100,1,25,0,131,1,83,0,124,0,115,92,124,5,83, + 0,116,3,124,0,131,1,116,3,124,0,160,2,100,3,161, + 1,100,1,25,0,131,1,24,0,125,8,116,4,106,5,124, + 5,106,6,100,2,116,3,124,5,106,6,131,1,124,8,24, + 0,133,2,25,0,25,0,83,0,110,12,116,7,124,5,124, + 3,116,0,131,3,83,0,100,2,83,0,41,4,97,215,1, + 0,0,73,109,112,111,114,116,32,97,32,109,111,100,117,108, + 101,46,10,10,32,32,32,32,84,104,101,32,39,103,108,111, + 98,97,108,115,39,32,97,114,103,117,109,101,110,116,32,105, + 115,32,117,115,101,100,32,116,111,32,105,110,102,101,114,32, + 119,104,101,114,101,32,116,104,101,32,105,109,112,111,114,116, + 32,105,115,32,111,99,99,117,114,114,105,110,103,32,102,114, + 111,109,10,32,32,32,32,116,111,32,104,97,110,100,108,101, + 32,114,101,108,97,116,105,118,101,32,105,109,112,111,114,116, + 115,46,32,84,104,101,32,39,108,111,99,97,108,115,39,32, + 97,114,103,117,109,101,110,116,32,105,115,32,105,103,110,111, + 114,101,100,46,32,84,104,101,10,32,32,32,32,39,102,114, + 111,109,108,105,115,116,39,32,97,114,103,117,109,101,110,116, + 32,115,112,101,99,105,102,105,101,115,32,119,104,97,116,32, + 115,104,111,117,108,100,32,101,120,105,115,116,32,97,115,32, + 97,116,116,114,105,98,117,116,101,115,32,111,110,32,116,104, + 101,32,109,111,100,117,108,101,10,32,32,32,32,98,101,105, + 110,103,32,105,109,112,111,114,116,101,100,32,40,101,46,103, + 46,32,96,96,102,114,111,109,32,109,111,100,117,108,101,32, + 105,109,112,111,114,116,32,60,102,114,111,109,108,105,115,116, + 62,96,96,41,46,32,32,84,104,101,32,39,108,101,118,101, + 108,39,10,32,32,32,32,97,114,103,117,109,101,110,116,32, + 114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,112, + 97,99,107,97,103,101,32,108,111,99,97,116,105,111,110,32, + 116,111,32,105,109,112,111,114,116,32,102,114,111,109,32,105, + 110,32,97,32,114,101,108,97,116,105,118,101,10,32,32,32, + 32,105,109,112,111,114,116,32,40,101,46,103,46,32,96,96, + 102,114,111,109,32,46,46,112,107,103,32,105,109,112,111,114, + 116,32,109,111,100,96,96,32,119,111,117,108,100,32,104,97, + 118,101,32,97,32,39,108,101,118,101,108,39,32,111,102,32, + 50,41,46,10,10,32,32,32,32,114,19,0,0,0,78,114, + 117,0,0,0,41,8,114,181,0,0,0,114,191,0,0,0, + 218,9,112,97,114,116,105,116,105,111,110,114,158,0,0,0, + 114,14,0,0,0,114,79,0,0,0,114,1,0,0,0,114, + 185,0,0,0,41,9,114,15,0,0,0,114,190,0,0,0, + 218,6,108,111,99,97,108,115,114,186,0,0,0,114,161,0, + 0,0,114,83,0,0,0,90,8,103,108,111,98,97,108,115, + 95,114,160,0,0,0,90,7,99,117,116,95,111,102,102,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,10, + 95,95,105,109,112,111,114,116,95,95,38,4,0,0,115,26, + 0,0,0,0,11,8,1,10,2,16,1,8,1,12,1,4, + 3,8,1,18,1,4,1,4,4,26,3,32,2,114,194,0, + 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,67,0,0,0,115,38,0,0,0,116,0,160,1, + 124,0,161,1,125,1,124,1,100,0,107,8,114,30,116,2, + 100,1,124,0,23,0,131,1,130,1,116,3,124,1,131,1, + 83,0,41,2,78,122,25,110,111,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,32,110,97,109,101,100,32, + 41,4,114,141,0,0,0,114,145,0,0,0,114,70,0,0, + 0,114,140,0,0,0,41,2,114,15,0,0,0,114,82,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,218,18,95,98,117,105,108,116,105,110,95,102,114,111,109, + 95,110,97,109,101,73,4,0,0,115,8,0,0,0,0,1, + 10,1,8,1,12,1,114,195,0,0,0,99,2,0,0,0, + 0,0,0,0,10,0,0,0,5,0,0,0,67,0,0,0, + 115,174,0,0,0,124,1,97,0,124,0,97,1,116,2,116, + 1,131,1,125,2,120,86,116,1,106,3,160,4,161,0,68, + 0,93,72,92,2,125,3,125,4,116,5,124,4,124,2,131, + 2,114,28,124,3,116,1,106,6,107,6,114,62,116,7,125, + 5,110,18,116,0,160,8,124,3,161,1,114,28,116,9,125, + 5,110,2,113,28,116,10,124,4,124,5,131,2,125,6,116, + 11,124,6,124,4,131,2,1,0,113,28,87,0,116,1,106, + 3,116,12,25,0,125,7,120,54,100,1,68,0,93,46,125, + 8,124,8,116,1,106,3,107,7,114,144,116,13,124,8,131, + 1,125,9,110,10,116,1,106,3,124,8,25,0,125,9,116, + 14,124,7,124,8,124,9,131,3,1,0,113,120,87,0,100, + 2,83,0,41,3,122,250,83,101,116,117,112,32,105,109,112, + 111,114,116,108,105,98,32,98,121,32,105,109,112,111,114,116, + 105,110,103,32,110,101,101,100,101,100,32,98,117,105,108,116, + 45,105,110,32,109,111,100,117,108,101,115,32,97,110,100,32, + 105,110,106,101,99,116,105,110,103,32,116,104,101,109,10,32, + 32,32,32,105,110,116,111,32,116,104,101,32,103,108,111,98, + 97,108,32,110,97,109,101,115,112,97,99,101,46,10,10,32, + 32,32,32,65,115,32,115,121,115,32,105,115,32,110,101,101, + 100,101,100,32,102,111,114,32,115,121,115,46,109,111,100,117, + 108,101,115,32,97,99,99,101,115,115,32,97,110,100,32,95, + 105,109,112,32,105,115,32,110,101,101,100,101,100,32,116,111, + 32,108,111,97,100,32,98,117,105,108,116,45,105,110,10,32, + 32,32,32,109,111,100,117,108,101,115,44,32,116,104,111,115, + 101,32,116,119,111,32,109,111,100,117,108,101,115,32,109,117, + 115,116,32,98,101,32,101,120,112,108,105,99,105,116,108,121, + 32,112,97,115,115,101,100,32,105,110,46,10,10,32,32,32, + 32,41,3,114,20,0,0,0,114,166,0,0,0,114,56,0, + 0,0,78,41,15,114,49,0,0,0,114,14,0,0,0,114, + 13,0,0,0,114,79,0,0,0,218,5,105,116,101,109,115, + 114,170,0,0,0,114,69,0,0,0,114,141,0,0,0,114, + 75,0,0,0,114,151,0,0,0,114,128,0,0,0,114,133, + 0,0,0,114,1,0,0,0,114,195,0,0,0,114,5,0, + 0,0,41,10,218,10,115,121,115,95,109,111,100,117,108,101, + 218,11,95,105,109,112,95,109,111,100,117,108,101,90,11,109, + 111,100,117,108,101,95,116,121,112,101,114,15,0,0,0,114, + 83,0,0,0,114,93,0,0,0,114,82,0,0,0,90,11, + 115,101,108,102,95,109,111,100,117,108,101,90,12,98,117,105, + 108,116,105,110,95,110,97,109,101,90,14,98,117,105,108,116, + 105,110,95,109,111,100,117,108,101,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,218,6,95,115,101,116,117,112, + 80,4,0,0,115,36,0,0,0,0,9,4,1,4,3,8, + 1,20,1,10,1,10,1,6,1,10,1,6,2,2,1,10, + 1,14,3,10,1,10,1,10,1,10,2,10,1,114,199,0, + 0,0,99,2,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,67,0,0,0,115,38,0,0,0,116,0,124,0, + 124,1,131,2,1,0,116,1,106,2,160,3,116,4,161,1, + 1,0,116,1,106,2,160,3,116,5,161,1,1,0,100,1, + 83,0,41,2,122,48,73,110,115,116,97,108,108,32,105,109, + 112,111,114,116,101,114,115,32,102,111,114,32,98,117,105,108, + 116,105,110,32,97,110,100,32,102,114,111,122,101,110,32,109, + 111,100,117,108,101,115,78,41,6,114,199,0,0,0,114,14, + 0,0,0,114,165,0,0,0,114,109,0,0,0,114,141,0, + 0,0,114,151,0,0,0,41,2,114,197,0,0,0,114,198, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,23,95,102,105,110,100,95,97,110,100,95,108,111, - 97,100,95,117,110,108,111,99,107,101,100,168,3,0,0,115, - 42,0,0,0,0,1,4,1,14,1,4,1,10,1,10,2, - 10,1,10,1,10,1,2,1,10,1,14,1,16,1,20,1, - 10,1,8,1,20,2,8,1,4,2,10,1,22,1,114,179, - 0,0,0,99,2,0,0,0,0,0,0,0,4,0,0,0, - 11,0,0,0,67,0,0,0,115,94,0,0,0,116,0,124, - 0,131,1,143,38,1,0,116,1,106,2,160,3,124,0,116, - 4,161,2,125,2,124,2,116,4,107,8,114,42,116,5,124, - 0,124,1,131,2,83,0,87,0,100,1,81,0,82,0,88, - 0,124,2,100,1,107,8,114,82,100,2,160,6,124,0,161, - 1,125,3,116,7,124,3,124,0,100,3,141,2,130,1,116, - 8,124,0,131,1,1,0,124,2,83,0,41,4,122,25,70, - 105,110,100,32,97,110,100,32,108,111,97,100,32,116,104,101, - 32,109,111,100,117,108,101,46,78,122,40,105,109,112,111,114, - 116,32,111,102,32,123,125,32,104,97,108,116,101,100,59,32, - 78,111,110,101,32,105,110,32,115,121,115,46,109,111,100,117, - 108,101,115,41,1,114,15,0,0,0,41,9,114,42,0,0, - 0,114,14,0,0,0,114,80,0,0,0,114,30,0,0,0, - 218,14,95,78,69,69,68,83,95,76,79,65,68,73,78,71, - 114,179,0,0,0,114,38,0,0,0,114,177,0,0,0,114, - 57,0,0,0,41,4,114,15,0,0,0,114,178,0,0,0, - 114,84,0,0,0,114,68,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,14,95,102,105,110,100, - 95,97,110,100,95,108,111,97,100,198,3,0,0,115,20,0, - 0,0,0,2,10,1,14,1,8,1,20,2,8,1,4,1, - 6,1,12,2,8,1,114,181,0,0,0,114,19,0,0,0, - 99,3,0,0,0,0,0,0,0,3,0,0,0,4,0,0, - 0,67,0,0,0,115,42,0,0,0,116,0,124,0,124,1, - 124,2,131,3,1,0,124,2,100,1,107,4,114,32,116,1, - 124,0,124,1,124,2,131,3,125,0,116,2,124,0,116,3, - 131,2,83,0,41,2,97,50,1,0,0,73,109,112,111,114, - 116,32,97,110,100,32,114,101,116,117,114,110,32,116,104,101, - 32,109,111,100,117,108,101,32,98,97,115,101,100,32,111,110, - 32,105,116,115,32,110,97,109,101,44,32,116,104,101,32,112, - 97,99,107,97,103,101,32,116,104,101,32,99,97,108,108,32, - 105,115,10,32,32,32,32,98,101,105,110,103,32,109,97,100, - 101,32,102,114,111,109,44,32,97,110,100,32,116,104,101,32, - 108,101,118,101,108,32,97,100,106,117,115,116,109,101,110,116, - 46,10,10,32,32,32,32,84,104,105,115,32,102,117,110,99, - 116,105,111,110,32,114,101,112,114,101,115,101,110,116,115,32, - 116,104,101,32,103,114,101,97,116,101,115,116,32,99,111,109, - 109,111,110,32,100,101,110,111,109,105,110,97,116,111,114,32, - 111,102,32,102,117,110,99,116,105,111,110,97,108,105,116,121, - 10,32,32,32,32,98,101,116,119,101,101,110,32,105,109,112, - 111,114,116,95,109,111,100,117,108,101,32,97,110,100,32,95, - 95,105,109,112,111,114,116,95,95,46,32,84,104,105,115,32, - 105,110,99,108,117,100,101,115,32,115,101,116,116,105,110,103, - 32,95,95,112,97,99,107,97,103,101,95,95,32,105,102,10, - 32,32,32,32,116,104,101,32,108,111,97,100,101,114,32,100, - 105,100,32,110,111,116,46,10,10,32,32,32,32,114,19,0, - 0,0,41,4,114,174,0,0,0,114,163,0,0,0,114,181, - 0,0,0,218,11,95,103,99,100,95,105,109,112,111,114,116, - 41,3,114,15,0,0,0,114,161,0,0,0,114,162,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,182,0,0,0,214,3,0,0,115,8,0,0,0,0,9, - 12,1,8,1,12,1,114,182,0,0,0,41,1,218,9,114, - 101,99,117,114,115,105,118,101,99,3,0,0,0,1,0,0, - 0,8,0,0,0,17,0,0,0,67,0,0,0,115,234,0, - 0,0,116,0,124,0,100,1,131,2,114,230,120,218,124,1, - 68,0,93,210,125,4,116,1,124,4,116,2,131,2,115,78, - 124,3,114,46,124,0,106,3,100,2,23,0,125,5,110,4, - 100,3,125,5,116,4,100,4,124,5,155,0,100,5,116,5, - 124,4,131,1,106,3,155,0,157,4,131,1,130,1,113,16, - 124,4,100,6,107,2,114,120,124,3,115,226,116,0,124,0, - 100,7,131,2,114,226,116,6,124,0,124,0,106,7,124,2, - 100,8,100,9,141,4,1,0,113,16,116,0,124,0,124,4, - 131,2,115,16,100,10,160,8,124,0,106,3,124,4,161,2, - 125,6,121,14,116,9,124,2,124,6,131,2,1,0,87,0, - 113,16,4,0,116,10,107,10,114,224,1,0,125,7,1,0, - 122,38,124,7,106,11,124,6,107,2,114,206,116,12,106,13, - 160,14,124,6,116,15,161,2,100,11,107,9,114,206,119,16, - 130,0,87,0,89,0,100,11,100,11,125,7,126,7,88,0, - 113,16,88,0,113,16,87,0,124,0,83,0,41,12,122,238, - 70,105,103,117,114,101,32,111,117,116,32,119,104,97,116,32, - 95,95,105,109,112,111,114,116,95,95,32,115,104,111,117,108, - 100,32,114,101,116,117,114,110,46,10,10,32,32,32,32,84, - 104,101,32,105,109,112,111,114,116,95,32,112,97,114,97,109, - 101,116,101,114,32,105,115,32,97,32,99,97,108,108,97,98, - 108,101,32,119,104,105,99,104,32,116,97,107,101,115,32,116, - 104,101,32,110,97,109,101,32,111,102,32,109,111,100,117,108, - 101,32,116,111,10,32,32,32,32,105,109,112,111,114,116,46, - 32,73,116,32,105,115,32,114,101,113,117,105,114,101,100,32, - 116,111,32,100,101,99,111,117,112,108,101,32,116,104,101,32, - 102,117,110,99,116,105,111,110,32,102,114,111,109,32,97,115, - 115,117,109,105,110,103,32,105,109,112,111,114,116,108,105,98, - 39,115,10,32,32,32,32,105,109,112,111,114,116,32,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,32,105,115,32, - 100,101,115,105,114,101,100,46,10,10,32,32,32,32,114,128, - 0,0,0,122,8,46,95,95,97,108,108,95,95,122,13,96, - 96,102,114,111,109,32,108,105,115,116,39,39,122,8,73,116, - 101,109,32,105,110,32,122,18,32,109,117,115,116,32,98,101, - 32,115,116,114,44,32,110,111,116,32,250,1,42,218,7,95, - 95,97,108,108,95,95,84,41,1,114,183,0,0,0,122,5, - 123,125,46,123,125,78,41,16,114,4,0,0,0,114,171,0, - 0,0,114,172,0,0,0,114,1,0,0,0,114,173,0,0, - 0,114,13,0,0,0,218,16,95,104,97,110,100,108,101,95, - 102,114,111,109,108,105,115,116,114,185,0,0,0,114,38,0, - 0,0,114,59,0,0,0,114,177,0,0,0,114,15,0,0, - 0,114,14,0,0,0,114,80,0,0,0,114,30,0,0,0, - 114,180,0,0,0,41,8,114,84,0,0,0,218,8,102,114, - 111,109,108,105,115,116,114,178,0,0,0,114,183,0,0,0, - 218,1,120,90,5,119,104,101,114,101,90,9,102,114,111,109, - 95,110,97,109,101,90,3,101,120,99,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,186,0,0,0,229,3, - 0,0,115,42,0,0,0,0,10,10,1,10,1,10,1,4, - 1,12,2,4,1,28,2,8,1,14,1,10,1,10,1,10, - 1,14,1,2,1,14,1,16,4,10,1,18,1,2,1,24, - 1,114,186,0,0,0,99,1,0,0,0,0,0,0,0,3, - 0,0,0,6,0,0,0,67,0,0,0,115,146,0,0,0, - 124,0,160,0,100,1,161,1,125,1,124,0,160,0,100,2, - 161,1,125,2,124,1,100,3,107,9,114,82,124,2,100,3, - 107,9,114,78,124,1,124,2,106,1,107,3,114,78,116,2, - 106,3,100,4,124,1,155,2,100,5,124,2,106,1,155,2, - 100,6,157,5,116,4,100,7,100,8,141,3,1,0,124,1, - 83,0,124,2,100,3,107,9,114,96,124,2,106,1,83,0, - 116,2,106,3,100,9,116,4,100,7,100,8,141,3,1,0, - 124,0,100,10,25,0,125,1,100,11,124,0,107,7,114,142, - 124,1,160,5,100,12,161,1,100,13,25,0,125,1,124,1, - 83,0,41,14,122,167,67,97,108,99,117,108,97,116,101,32, - 119,104,97,116,32,95,95,112,97,99,107,97,103,101,95,95, - 32,115,104,111,117,108,100,32,98,101,46,10,10,32,32,32, - 32,95,95,112,97,99,107,97,103,101,95,95,32,105,115,32, - 110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116, - 111,32,98,101,32,100,101,102,105,110,101,100,32,111,114,32, - 99,111,117,108,100,32,98,101,32,115,101,116,32,116,111,32, - 78,111,110,101,10,32,32,32,32,116,111,32,114,101,112,114, - 101,115,101,110,116,32,116,104,97,116,32,105,116,115,32,112, - 114,111,112,101,114,32,118,97,108,117,101,32,105,115,32,117, - 110,107,110,111,119,110,46,10,10,32,32,32,32,114,131,0, - 0,0,114,90,0,0,0,78,122,32,95,95,112,97,99,107, - 97,103,101,95,95,32,33,61,32,95,95,115,112,101,99,95, - 95,46,112,97,114,101,110,116,32,40,122,4,32,33,61,32, - 250,1,41,233,3,0,0,0,41,1,90,10,115,116,97,99, - 107,108,101,118,101,108,122,89,99,97,110,39,116,32,114,101, - 115,111,108,118,101,32,112,97,99,107,97,103,101,32,102,114, - 111,109,32,95,95,115,112,101,99,95,95,32,111,114,32,95, - 95,112,97,99,107,97,103,101,95,95,44,32,102,97,108,108, - 105,110,103,32,98,97,99,107,32,111,110,32,95,95,110,97, - 109,101,95,95,32,97,110,100,32,95,95,112,97,116,104,95, - 95,114,1,0,0,0,114,128,0,0,0,114,118,0,0,0, - 114,19,0,0,0,41,6,114,30,0,0,0,114,120,0,0, - 0,114,167,0,0,0,114,168,0,0,0,114,169,0,0,0, - 114,119,0,0,0,41,3,218,7,103,108,111,98,97,108,115, - 114,161,0,0,0,114,83,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,17,95,99,97,108,99, - 95,95,95,112,97,99,107,97,103,101,95,95,11,4,0,0, - 115,30,0,0,0,0,7,10,1,10,1,8,1,18,1,22, - 2,10,1,4,1,8,1,6,2,6,2,10,1,8,1,8, - 1,14,1,114,192,0,0,0,99,5,0,0,0,0,0,0, - 0,9,0,0,0,5,0,0,0,67,0,0,0,115,166,0, - 0,0,124,4,100,1,107,2,114,18,116,0,124,0,131,1, - 125,5,110,36,124,1,100,2,107,9,114,30,124,1,110,2, - 105,0,125,6,116,1,124,6,131,1,125,7,116,0,124,0, - 124,7,124,4,131,3,125,5,124,3,115,150,124,4,100,1, - 107,2,114,84,116,0,124,0,160,2,100,3,161,1,100,1, - 25,0,131,1,83,0,124,0,115,92,124,5,83,0,116,3, - 124,0,131,1,116,3,124,0,160,2,100,3,161,1,100,1, - 25,0,131,1,24,0,125,8,116,4,106,5,124,5,106,6, - 100,2,116,3,124,5,106,6,131,1,124,8,24,0,133,2, - 25,0,25,0,83,0,110,12,116,7,124,5,124,3,116,0, - 131,3,83,0,100,2,83,0,41,4,97,215,1,0,0,73, - 109,112,111,114,116,32,97,32,109,111,100,117,108,101,46,10, - 10,32,32,32,32,84,104,101,32,39,103,108,111,98,97,108, - 115,39,32,97,114,103,117,109,101,110,116,32,105,115,32,117, - 115,101,100,32,116,111,32,105,110,102,101,114,32,119,104,101, - 114,101,32,116,104,101,32,105,109,112,111,114,116,32,105,115, - 32,111,99,99,117,114,114,105,110,103,32,102,114,111,109,10, - 32,32,32,32,116,111,32,104,97,110,100,108,101,32,114,101, - 108,97,116,105,118,101,32,105,109,112,111,114,116,115,46,32, - 84,104,101,32,39,108,111,99,97,108,115,39,32,97,114,103, - 117,109,101,110,116,32,105,115,32,105,103,110,111,114,101,100, - 46,32,84,104,101,10,32,32,32,32,39,102,114,111,109,108, - 105,115,116,39,32,97,114,103,117,109,101,110,116,32,115,112, - 101,99,105,102,105,101,115,32,119,104,97,116,32,115,104,111, - 117,108,100,32,101,120,105,115,116,32,97,115,32,97,116,116, - 114,105,98,117,116,101,115,32,111,110,32,116,104,101,32,109, - 111,100,117,108,101,10,32,32,32,32,98,101,105,110,103,32, - 105,109,112,111,114,116,101,100,32,40,101,46,103,46,32,96, - 96,102,114,111,109,32,109,111,100,117,108,101,32,105,109,112, - 111,114,116,32,60,102,114,111,109,108,105,115,116,62,96,96, - 41,46,32,32,84,104,101,32,39,108,101,118,101,108,39,10, - 32,32,32,32,97,114,103,117,109,101,110,116,32,114,101,112, - 114,101,115,101,110,116,115,32,116,104,101,32,112,97,99,107, - 97,103,101,32,108,111,99,97,116,105,111,110,32,116,111,32, - 105,109,112,111,114,116,32,102,114,111,109,32,105,110,32,97, - 32,114,101,108,97,116,105,118,101,10,32,32,32,32,105,109, - 112,111,114,116,32,40,101,46,103,46,32,96,96,102,114,111, - 109,32,46,46,112,107,103,32,105,109,112,111,114,116,32,109, - 111,100,96,96,32,119,111,117,108,100,32,104,97,118,101,32, - 97,32,39,108,101,118,101,108,39,32,111,102,32,50,41,46, - 10,10,32,32,32,32,114,19,0,0,0,78,114,118,0,0, - 0,41,8,114,182,0,0,0,114,192,0,0,0,218,9,112, - 97,114,116,105,116,105,111,110,114,159,0,0,0,114,14,0, - 0,0,114,80,0,0,0,114,1,0,0,0,114,186,0,0, - 0,41,9,114,15,0,0,0,114,191,0,0,0,218,6,108, - 111,99,97,108,115,114,187,0,0,0,114,162,0,0,0,114, - 84,0,0,0,90,8,103,108,111,98,97,108,115,95,114,161, - 0,0,0,90,7,99,117,116,95,111,102,102,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,218,10,95,95,105, - 109,112,111,114,116,95,95,38,4,0,0,115,26,0,0,0, - 0,11,8,1,10,2,16,1,8,1,12,1,4,3,8,1, - 18,1,4,1,4,4,26,3,32,2,114,195,0,0,0,99, - 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 67,0,0,0,115,38,0,0,0,116,0,160,1,124,0,161, - 1,125,1,124,1,100,0,107,8,114,30,116,2,100,1,124, - 0,23,0,131,1,130,1,116,3,124,1,131,1,83,0,41, - 2,78,122,25,110,111,32,98,117,105,108,116,45,105,110,32, - 109,111,100,117,108,101,32,110,97,109,101,100,32,41,4,114, - 142,0,0,0,114,146,0,0,0,114,71,0,0,0,114,141, - 0,0,0,41,2,114,15,0,0,0,114,83,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,18, - 95,98,117,105,108,116,105,110,95,102,114,111,109,95,110,97, - 109,101,73,4,0,0,115,8,0,0,0,0,1,10,1,8, - 1,12,1,114,196,0,0,0,99,2,0,0,0,0,0,0, - 0,10,0,0,0,5,0,0,0,67,0,0,0,115,174,0, - 0,0,124,1,97,0,124,0,97,1,116,2,116,1,131,1, - 125,2,120,86,116,1,106,3,160,4,161,0,68,0,93,72, - 92,2,125,3,125,4,116,5,124,4,124,2,131,2,114,28, - 124,3,116,1,106,6,107,6,114,62,116,7,125,5,110,18, - 116,0,160,8,124,3,161,1,114,28,116,9,125,5,110,2, - 113,28,116,10,124,4,124,5,131,2,125,6,116,11,124,6, - 124,4,131,2,1,0,113,28,87,0,116,1,106,3,116,12, - 25,0,125,7,120,54,100,5,68,0,93,46,125,8,124,8, - 116,1,106,3,107,7,114,144,116,13,124,8,131,1,125,9, - 110,10,116,1,106,3,124,8,25,0,125,9,116,14,124,7, - 124,8,124,9,131,3,1,0,113,120,87,0,100,4,83,0, - 41,6,122,250,83,101,116,117,112,32,105,109,112,111,114,116, - 108,105,98,32,98,121,32,105,109,112,111,114,116,105,110,103, - 32,110,101,101,100,101,100,32,98,117,105,108,116,45,105,110, - 32,109,111,100,117,108,101,115,32,97,110,100,32,105,110,106, - 101,99,116,105,110,103,32,116,104,101,109,10,32,32,32,32, - 105,110,116,111,32,116,104,101,32,103,108,111,98,97,108,32, - 110,97,109,101,115,112,97,99,101,46,10,10,32,32,32,32, - 65,115,32,115,121,115,32,105,115,32,110,101,101,100,101,100, - 32,102,111,114,32,115,121,115,46,109,111,100,117,108,101,115, - 32,97,99,99,101,115,115,32,97,110,100,32,95,105,109,112, - 32,105,115,32,110,101,101,100,101,100,32,116,111,32,108,111, - 97,100,32,98,117,105,108,116,45,105,110,10,32,32,32,32, - 109,111,100,117,108,101,115,44,32,116,104,111,115,101,32,116, - 119,111,32,109,111,100,117,108,101,115,32,109,117,115,116,32, - 98,101,32,101,120,112,108,105,99,105,116,108,121,32,112,97, - 115,115,101,100,32,105,110,46,10,10,32,32,32,32,114,20, - 0,0,0,114,167,0,0,0,114,56,0,0,0,78,41,3, - 114,20,0,0,0,114,167,0,0,0,114,56,0,0,0,41, - 15,114,49,0,0,0,114,14,0,0,0,114,13,0,0,0, - 114,80,0,0,0,218,5,105,116,101,109,115,114,171,0,0, - 0,114,70,0,0,0,114,142,0,0,0,114,76,0,0,0, - 114,152,0,0,0,114,129,0,0,0,114,134,0,0,0,114, - 1,0,0,0,114,196,0,0,0,114,5,0,0,0,41,10, - 218,10,115,121,115,95,109,111,100,117,108,101,218,11,95,105, - 109,112,95,109,111,100,117,108,101,90,11,109,111,100,117,108, - 101,95,116,121,112,101,114,15,0,0,0,114,84,0,0,0, - 114,94,0,0,0,114,83,0,0,0,90,11,115,101,108,102, - 95,109,111,100,117,108,101,90,12,98,117,105,108,116,105,110, - 95,110,97,109,101,90,14,98,117,105,108,116,105,110,95,109, - 111,100,117,108,101,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,6,95,115,101,116,117,112,80,4,0,0, - 115,36,0,0,0,0,9,4,1,4,3,8,1,20,1,10, - 1,10,1,6,1,10,1,6,2,2,1,10,1,14,3,10, - 1,10,1,10,1,10,2,10,1,114,200,0,0,0,99,2, - 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, - 0,0,0,115,38,0,0,0,116,0,124,0,124,1,131,2, - 1,0,116,1,106,2,160,3,116,4,161,1,1,0,116,1, - 106,2,160,3,116,5,161,1,1,0,100,1,83,0,41,2, - 122,48,73,110,115,116,97,108,108,32,105,109,112,111,114,116, - 101,114,115,32,102,111,114,32,98,117,105,108,116,105,110,32, - 97,110,100,32,102,114,111,122,101,110,32,109,111,100,117,108, - 101,115,78,41,6,114,200,0,0,0,114,14,0,0,0,114, - 166,0,0,0,114,110,0,0,0,114,142,0,0,0,114,152, - 0,0,0,41,2,114,198,0,0,0,114,199,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,8, - 95,105,110,115,116,97,108,108,115,4,0,0,115,6,0,0, - 0,0,2,10,2,12,1,114,201,0,0,0,99,0,0,0, - 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, - 0,115,32,0,0,0,100,1,100,2,108,0,125,0,124,0, - 97,1,124,0,160,2,116,3,106,4,116,5,25,0,161,1, - 1,0,100,2,83,0,41,3,122,57,73,110,115,116,97,108, - 108,32,105,109,112,111,114,116,101,114,115,32,116,104,97,116, - 32,114,101,113,117,105,114,101,32,101,120,116,101,114,110,97, - 108,32,102,105,108,101,115,121,115,116,101,109,32,97,99,99, - 101,115,115,114,19,0,0,0,78,41,6,218,26,95,102,114, - 111,122,101,110,95,105,109,112,111,114,116,108,105,98,95,101, - 120,116,101,114,110,97,108,114,116,0,0,0,114,201,0,0, - 0,114,14,0,0,0,114,80,0,0,0,114,1,0,0,0, - 41,1,114,202,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,27,95,105,110,115,116,97,108,108, - 95,101,120,116,101,114,110,97,108,95,105,109,112,111,114,116, - 101,114,115,123,4,0,0,115,6,0,0,0,0,3,8,1, - 4,1,114,203,0,0,0,41,2,78,78,41,1,78,41,2, - 78,114,19,0,0,0,41,51,114,3,0,0,0,114,116,0, - 0,0,114,12,0,0,0,114,16,0,0,0,114,51,0,0, - 0,114,29,0,0,0,114,36,0,0,0,114,17,0,0,0, - 114,18,0,0,0,114,41,0,0,0,114,42,0,0,0,114, - 45,0,0,0,114,57,0,0,0,114,59,0,0,0,114,69, - 0,0,0,114,75,0,0,0,114,78,0,0,0,114,85,0, - 0,0,114,96,0,0,0,114,97,0,0,0,114,103,0,0, - 0,114,79,0,0,0,114,129,0,0,0,114,134,0,0,0, - 114,137,0,0,0,114,92,0,0,0,114,81,0,0,0,114, - 140,0,0,0,114,141,0,0,0,114,82,0,0,0,114,142, - 0,0,0,114,152,0,0,0,114,157,0,0,0,114,163,0, - 0,0,114,165,0,0,0,114,170,0,0,0,114,174,0,0, - 0,90,15,95,69,82,82,95,77,83,71,95,80,82,69,70, - 73,88,114,176,0,0,0,114,179,0,0,0,218,6,111,98, - 106,101,99,116,114,180,0,0,0,114,181,0,0,0,114,182, - 0,0,0,114,186,0,0,0,114,192,0,0,0,114,195,0, - 0,0,114,196,0,0,0,114,200,0,0,0,114,201,0,0, - 0,114,203,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,218,8,60,109,111,100, - 117,108,101,62,25,0,0,0,115,96,0,0,0,4,0,4, - 2,8,8,8,8,4,2,4,3,16,4,14,68,14,21,14, - 16,8,37,8,17,8,11,14,8,8,11,8,12,8,16,8, - 36,14,27,14,101,16,26,10,45,14,60,8,17,8,17,8, - 24,8,29,8,23,8,15,14,73,14,77,14,13,8,9,8, - 9,10,47,8,16,4,1,8,2,8,27,6,3,8,16,10, - 15,14,38,8,27,18,35,8,7,8,35,8,8, + 0,0,218,8,95,105,110,115,116,97,108,108,115,4,0,0, + 115,6,0,0,0,0,2,10,2,12,1,114,200,0,0,0, + 99,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, + 0,67,0,0,0,115,32,0,0,0,100,1,100,2,108,0, + 125,0,124,0,97,1,124,0,160,2,116,3,106,4,116,5, + 25,0,161,1,1,0,100,2,83,0,41,3,122,57,73,110, + 115,116,97,108,108,32,105,109,112,111,114,116,101,114,115,32, + 116,104,97,116,32,114,101,113,117,105,114,101,32,101,120,116, + 101,114,110,97,108,32,102,105,108,101,115,121,115,116,101,109, + 32,97,99,99,101,115,115,114,19,0,0,0,78,41,6,218, + 26,95,102,114,111,122,101,110,95,105,109,112,111,114,116,108, + 105,98,95,101,120,116,101,114,110,97,108,114,115,0,0,0, + 114,200,0,0,0,114,14,0,0,0,114,79,0,0,0,114, + 1,0,0,0,41,1,114,201,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,218,27,95,105,110,115, + 116,97,108,108,95,101,120,116,101,114,110,97,108,95,105,109, + 112,111,114,116,101,114,115,123,4,0,0,115,6,0,0,0, + 0,3,8,1,4,1,114,202,0,0,0,41,2,78,78,41, + 1,78,41,2,78,114,19,0,0,0,41,4,78,78,114,10, + 0,0,0,114,19,0,0,0,41,51,114,3,0,0,0,114, + 115,0,0,0,114,12,0,0,0,114,16,0,0,0,114,51, + 0,0,0,114,29,0,0,0,114,36,0,0,0,114,17,0, + 0,0,114,18,0,0,0,114,41,0,0,0,114,42,0,0, + 0,114,45,0,0,0,114,57,0,0,0,114,59,0,0,0, + 114,68,0,0,0,114,74,0,0,0,114,77,0,0,0,114, + 84,0,0,0,114,95,0,0,0,114,96,0,0,0,114,102, + 0,0,0,114,78,0,0,0,114,128,0,0,0,114,133,0, + 0,0,114,136,0,0,0,114,91,0,0,0,114,80,0,0, + 0,114,139,0,0,0,114,140,0,0,0,114,81,0,0,0, + 114,141,0,0,0,114,151,0,0,0,114,156,0,0,0,114, + 162,0,0,0,114,164,0,0,0,114,169,0,0,0,114,173, + 0,0,0,90,15,95,69,82,82,95,77,83,71,95,80,82, + 69,70,73,88,114,175,0,0,0,114,178,0,0,0,218,6, + 111,98,106,101,99,116,114,179,0,0,0,114,180,0,0,0, + 114,181,0,0,0,114,185,0,0,0,114,191,0,0,0,114, + 194,0,0,0,114,195,0,0,0,114,199,0,0,0,114,200, + 0,0,0,114,202,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,8,60,109, + 111,100,117,108,101,62,25,0,0,0,115,96,0,0,0,4, + 0,4,2,8,8,8,8,4,2,4,3,16,4,14,68,14, + 21,14,16,8,37,8,17,8,11,14,8,8,11,8,12,8, + 16,8,36,14,27,14,101,16,26,10,45,14,60,8,17,8, + 17,8,24,8,29,8,23,8,15,14,73,14,77,14,13,8, + 9,8,9,10,47,8,16,4,1,8,2,8,27,6,3,8, + 16,10,15,14,38,8,27,10,35,8,7,8,35,8,8, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 907392c209d..6b900731c51 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1,40 +1,40 @@ /* 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,5,0,0, - 0,64,0,0,0,115,16,2,0,0,100,0,90,0,100,98, - 90,1,100,99,90,2,101,2,101,1,23,0,90,3,100,4, - 100,5,132,0,90,4,100,6,100,7,132,0,90,5,100,8, - 100,9,132,0,90,6,100,10,100,11,132,0,90,7,100,12, - 100,13,132,0,90,8,100,14,100,15,132,0,90,9,100,16, - 100,17,132,0,90,10,100,18,100,19,132,0,90,11,100,20, - 100,21,132,0,90,12,100,100,100,23,100,24,132,1,90,13, - 101,14,101,13,106,15,131,1,90,16,100,25,160,17,100,26, - 100,27,161,2,100,28,23,0,90,18,101,19,160,20,101,18, - 100,27,161,2,90,21,100,29,90,22,100,30,90,23,100,31, - 103,1,90,24,100,32,103,1,90,25,101,25,4,0,90,26, - 90,27,100,101,100,33,100,34,156,1,100,35,100,36,132,3, - 90,28,100,37,100,38,132,0,90,29,100,39,100,40,132,0, - 90,30,100,41,100,42,132,0,90,31,100,43,100,44,132,0, - 90,32,100,45,100,46,132,0,90,33,100,47,100,48,132,0, - 90,34,100,49,100,50,132,0,90,35,100,51,100,52,132,0, - 90,36,100,53,100,54,132,0,90,37,100,102,100,55,100,56, - 132,1,90,38,100,103,100,58,100,59,132,1,90,39,100,104, - 100,61,100,62,132,1,90,40,100,63,100,64,132,0,90,41, - 101,42,131,0,90,43,100,105,100,33,101,43,100,65,156,2, - 100,66,100,67,132,3,90,44,71,0,100,68,100,69,132,0, - 100,69,131,2,90,45,71,0,100,70,100,71,132,0,100,71, - 131,2,90,46,71,0,100,72,100,73,132,0,100,73,101,46, - 131,3,90,47,71,0,100,74,100,75,132,0,100,75,131,2, - 90,48,71,0,100,76,100,77,132,0,100,77,101,48,101,47, - 131,4,90,49,71,0,100,78,100,79,132,0,100,79,101,48, - 101,46,131,4,90,50,103,0,90,51,71,0,100,80,100,81, - 132,0,100,81,101,48,101,46,131,4,90,52,71,0,100,82, - 100,83,132,0,100,83,131,2,90,53,71,0,100,84,100,85, - 132,0,100,85,131,2,90,54,71,0,100,86,100,87,132,0, - 100,87,131,2,90,55,71,0,100,88,100,89,132,0,100,89, - 131,2,90,56,100,106,100,90,100,91,132,1,90,57,100,92, - 100,93,132,0,90,58,100,94,100,95,132,0,90,59,100,96, - 100,97,132,0,90,60,100,33,83,0,41,107,97,94,1,0, + 0,64,0,0,0,115,16,2,0,0,100,0,90,0,100,1, + 90,1,100,2,90,2,101,2,101,1,23,0,90,3,100,3, + 100,4,132,0,90,4,100,5,100,6,132,0,90,5,100,7, + 100,8,132,0,90,6,100,9,100,10,132,0,90,7,100,11, + 100,12,132,0,90,8,100,13,100,14,132,0,90,9,100,15, + 100,16,132,0,90,10,100,17,100,18,132,0,90,11,100,19, + 100,20,132,0,90,12,100,97,100,22,100,23,132,1,90,13, + 101,14,101,13,106,15,131,1,90,16,100,24,160,17,100,25, + 100,26,161,2,100,27,23,0,90,18,101,19,160,20,101,18, + 100,26,161,2,90,21,100,28,90,22,100,29,90,23,100,30, + 103,1,90,24,100,31,103,1,90,25,101,25,4,0,90,26, + 90,27,100,98,100,32,100,33,156,1,100,34,100,35,132,3, + 90,28,100,36,100,37,132,0,90,29,100,38,100,39,132,0, + 90,30,100,40,100,41,132,0,90,31,100,42,100,43,132,0, + 90,32,100,44,100,45,132,0,90,33,100,46,100,47,132,0, + 90,34,100,48,100,49,132,0,90,35,100,50,100,51,132,0, + 90,36,100,52,100,53,132,0,90,37,100,99,100,54,100,55, + 132,1,90,38,100,100,100,57,100,58,132,1,90,39,100,101, + 100,60,100,61,132,1,90,40,100,62,100,63,132,0,90,41, + 101,42,131,0,90,43,100,102,100,32,101,43,100,64,156,2, + 100,65,100,66,132,3,90,44,71,0,100,67,100,68,132,0, + 100,68,131,2,90,45,71,0,100,69,100,70,132,0,100,70, + 131,2,90,46,71,0,100,71,100,72,132,0,100,72,101,46, + 131,3,90,47,71,0,100,73,100,74,132,0,100,74,131,2, + 90,48,71,0,100,75,100,76,132,0,100,76,101,48,101,47, + 131,4,90,49,71,0,100,77,100,78,132,0,100,78,101,48, + 101,46,131,4,90,50,103,0,90,51,71,0,100,79,100,80, + 132,0,100,80,101,48,101,46,131,4,90,52,71,0,100,81, + 100,82,132,0,100,82,131,2,90,53,71,0,100,83,100,84, + 132,0,100,84,131,2,90,54,71,0,100,85,100,86,132,0, + 100,86,131,2,90,55,71,0,100,87,100,88,132,0,100,88, + 131,2,90,56,100,103,100,89,100,90,132,1,90,57,100,91, + 100,92,132,0,90,58,100,93,100,94,132,0,90,59,100,95, + 100,96,132,0,90,60,100,32,83,0,41,104,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, @@ -56,597 +56,596 @@ const unsigned char _Py_M__importlib_external[] = { 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,3,0,0,0,3,0,0,0,115,60,0,0,0,116,0, - 106,1,160,2,116,3,161,1,114,48,116,0,106,1,160,2, - 116,4,161,1,114,30,100,1,137,0,110,4,100,2,137,0, - 135,0,102,1,100,3,100,4,132,8,125,0,110,8,100,5, - 100,4,132,0,125,0,124,0,83,0,41,6,78,90,12,80, - 89,84,72,79,78,67,65,83,69,79,75,115,12,0,0,0, - 80,89,84,72,79,78,67,65,83,69,79,75,99,0,0,0, - 0,0,0,0,0,0,0,0,0,2,0,0,0,19,0,0, - 0,115,10,0,0,0,136,0,116,0,106,1,107,6,83,0, - 41,1,122,53,84,114,117,101,32,105,102,32,102,105,108,101, + 32,116,104,105,115,32,109,111,100,117,108,101,46,10,10,41, + 1,218,3,119,105,110,41,2,90,6,99,121,103,119,105,110, + 90,6,100,97,114,119,105,110,99,0,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,3,0,0,0,115,60,0, + 0,0,116,0,106,1,160,2,116,3,161,1,114,48,116,0, + 106,1,160,2,116,4,161,1,114,30,100,1,137,0,110,4, + 100,2,137,0,135,0,102,1,100,3,100,4,132,8,125,0, + 110,8,100,5,100,4,132,0,125,0,124,0,83,0,41,6, + 78,90,12,80,89,84,72,79,78,67,65,83,69,79,75,115, + 12,0,0,0,80,89,84,72,79,78,67,65,83,69,79,75, + 99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,19,0,0,0,115,10,0,0,0,136,0,116,0,106,1, + 107,6,83,0,41,1,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,41,2,218, + 3,95,111,115,90,7,101,110,118,105,114,111,110,169,0,41, + 1,218,3,107,101,121,114,2,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, + 37,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,83,0, + 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,41,2,218,3,95,111,115, - 90,7,101,110,118,105,114,111,110,169,0,41,1,218,3,107, - 101,121,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,37,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,83,0,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,6,0,0,0,114, - 7,0,0,0,41,0,0,0,115,2,0,0,0,0,2,41, - 5,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,218,35,95,67,65,83,69, - 95,73,78,83,69,78,83,73,84,73,86,69,95,80,76,65, - 84,70,79,82,77,83,95,83,84,82,95,75,69,89,41,1, - 114,7,0,0,0,114,4,0,0,0,41,1,114,5,0,0, - 0,114,6,0,0,0,218,16,95,109,97,107,101,95,114,101, - 108,97,120,95,99,97,115,101,30,0,0,0,115,14,0,0, - 0,0,1,12,1,12,1,6,2,4,2,14,4,8,3,114, - 13,0,0,0,99,1,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,67,0,0,0,115,20,0,0,0,116,0, - 124,0,131,1,100,1,64,0,160,1,100,2,100,3,161,2, - 83,0,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,6,0,0,0,218,7,95, - 119,95,108,111,110,103,47,0,0,0,115,2,0,0,0,0, - 2,114,19,0,0,0,99,1,0,0,0,0,0,0,0,1, - 0,0,0,4,0,0,0,67,0,0,0,115,12,0,0,0, - 116,0,160,1,124,0,100,1,161,2,83,0,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, - 15,0,0,0,41,2,114,16,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,6, - 0,0,0,218,7,95,114,95,108,111,110,103,52,0,0,0, - 115,2,0,0,0,0,2,114,21,0,0,0,99,0,0,0, - 0,0,0,0,0,1,0,0,0,4,0,0,0,71,0,0, - 0,115,20,0,0,0,116,0,160,1,100,1,100,2,132,0, - 124,0,68,0,131,1,161,1,83,0,41,3,122,31,82,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,5,0,0,0,83,0, - 0,0,115,26,0,0,0,103,0,124,0,93,18,125,1,124, - 1,114,4,124,1,160,0,116,1,161,1,145,2,113,4,83, - 0,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,6,0,0,0,250,10,60,108, - 105,115,116,99,111,109,112,62,59,0,0,0,115,2,0,0, - 0,6,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,6,0, - 0,0,218,10,95,112,97,116,104,95,106,111,105,110,57,0, - 0,0,115,4,0,0,0,0,2,10,1,114,30,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,96,0,0,0,116,0,116,1,131,1, - 100,1,107,2,114,36,124,0,160,2,116,3,161,1,92,3, - 125,1,125,2,125,3,124,1,124,3,102,2,83,0,120,50, - 116,4,124,0,131,1,68,0,93,38,125,4,124,4,116,1, - 107,6,114,46,124,0,106,5,124,4,100,1,100,2,141,2, - 92,2,125,1,125,3,124,1,124,3,102,2,83,0,113,46, - 87,0,100,3,124,0,102,2,83,0,41,4,122,32,82,101, - 112,108,97,99,101,109,101,110,116,32,102,111,114,32,111,115, - 46,112,97,116,104,46,115,112,108,105,116,40,41,46,233,1, - 0,0,0,41,1,90,8,109,97,120,115,112,108,105,116,218, - 0,41,6,218,3,108,101,110,114,23,0,0,0,218,10,114, - 112,97,114,116,105,116,105,111,110,114,27,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,18,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,218,11,95,112, - 97,116,104,95,115,112,108,105,116,63,0,0,0,115,16,0, - 0,0,0,2,12,1,16,1,8,1,14,1,8,1,18,1, - 12,1,114,40,0,0,0,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,10,0,0, - 0,116,0,160,1,124,0,161,1,83,0,41,1,122,126,83, - 116,97,116,32,116,104,101,32,112,97,116,104,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,37,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 218,10,95,112,97,116,104,95,115,116,97,116,75,0,0,0, - 115,2,0,0,0,0,7,114,41,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,48,0,0,0,121,12,116,0,124,0,131,1,125,2, - 87,0,110,20,4,0,116,1,107,10,114,32,1,0,1,0, - 1,0,100,1,83,0,88,0,124,2,106,2,100,2,64,0, - 124,1,107,2,83,0,41,3,122,49,84,101,115,116,32,119, - 104,101,116,104,101,114,32,116,104,101,32,112,97,116,104,32, - 105,115,32,116,104,101,32,115,112,101,99,105,102,105,101,100, - 32,109,111,100,101,32,116,121,112,101,46,70,105,0,240,0, - 0,41,3,114,41,0,0,0,218,7,79,83,69,114,114,111, - 114,218,7,115,116,95,109,111,100,101,41,3,114,37,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,6,0,0, - 0,218,18,95,112,97,116,104,95,105,115,95,109,111,100,101, - 95,116,121,112,101,85,0,0,0,115,10,0,0,0,0,2, - 2,1,12,1,14,1,6,1,114,45,0,0,0,99,1,0, - 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, - 0,0,115,10,0,0,0,116,0,124,0,100,1,131,2,83, - 0,41,2,122,31,82,101,112,108,97,99,101,109,101,110,116, - 32,102,111,114,32,111,115,46,112,97,116,104,46,105,115,102, - 105,108,101,46,105,0,128,0,0,41,1,114,45,0,0,0, - 41,1,114,37,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,12,95,112,97,116,104,95,105,115, - 102,105,108,101,94,0,0,0,115,2,0,0,0,0,2,114, - 46,0,0,0,99,1,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,115,22,0,0,0,124,0, - 115,12,116,0,160,1,161,0,125,0,116,2,124,0,100,1, - 131,2,83,0,41,2,122,30,82,101,112,108,97,99,101,109, - 101,110,116,32,102,111,114,32,111,115,46,112,97,116,104,46, - 105,115,100,105,114,46,105,0,64,0,0,41,3,114,3,0, - 0,0,218,6,103,101,116,99,119,100,114,45,0,0,0,41, - 1,114,37,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,11,95,112,97,116,104,95,105,115,100, - 105,114,99,0,0,0,115,6,0,0,0,0,2,4,1,8, - 1,114,48,0,0,0,233,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,162,0,0,0,100,1,160,0,124,0,116,1,124,0,131, - 1,161,2,125,3,116,2,160,3,124,3,116,2,106,4,116, - 2,106,5,66,0,116,2,106,6,66,0,124,2,100,2,64, - 0,161,3,125,4,121,50,116,7,160,8,124,4,100,3,161, - 2,143,16,125,5,124,5,160,9,124,1,161,1,1,0,87, - 0,100,4,81,0,82,0,88,0,116,2,160,10,124,3,124, - 0,161,2,1,0,87,0,110,58,4,0,116,11,107,10,114, - 156,1,0,1,0,1,0,121,14,116,2,160,12,124,3,161, - 1,1,0,87,0,110,20,4,0,116,11,107,10,114,148,1, - 0,1,0,1,0,89,0,110,2,88,0,130,0,89,0,110, - 2,88,0,100,4,83,0,41,5,122,162,66,101,115,116,45, - 101,102,102,111,114,116,32,102,117,110,99,116,105,111,110,32, - 116,111,32,119,114,105,116,101,32,100,97,116,97,32,116,111, - 32,97,32,112,97,116,104,32,97,116,111,109,105,99,97,108, - 108,121,46,10,32,32,32,32,66,101,32,112,114,101,112,97, - 114,101,100,32,116,111,32,104,97,110,100,108,101,32,97,32, - 70,105,108,101,69,120,105,115,116,115,69,114,114,111,114,32, - 105,102,32,99,111,110,99,117,114,114,101,110,116,32,119,114, - 105,116,105,110,103,32,111,102,32,116,104,101,10,32,32,32, - 32,116,101,109,112,111,114,97,114,121,32,102,105,108,101,32, - 105,115,32,97,116,116,101,109,112,116,101,100,46,122,5,123, - 125,46,123,125,105,182,1,0,0,90,2,119,98,78,41,13, - 218,6,102,111,114,109,97,116,218,2,105,100,114,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, - 42,0,0,0,90,6,117,110,108,105,110,107,41,6,114,37, - 0,0,0,218,4,100,97,116,97,114,44,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,6,0,0, - 0,218,13,95,119,114,105,116,101,95,97,116,111,109,105,99, - 106,0,0,0,115,26,0,0,0,0,5,16,1,6,1,26, - 1,2,3,14,1,20,1,16,1,14,1,2,1,14,1,14, - 1,6,1,114,58,0,0,0,105,64,13,0,0,233,2,0, - 0,0,114,15,0,0,0,115,2,0,0,0,13,10,90,11, - 95,95,112,121,99,97,99,104,101,95,95,122,4,111,112,116, - 45,122,3,46,112,121,122,4,46,112,121,99,78,41,1,218, - 12,111,112,116,105,109,105,122,97,116,105,111,110,99,2,0, - 0,0,1,0,0,0,11,0,0,0,6,0,0,0,67,0, - 0,0,115,244,0,0,0,124,1,100,1,107,9,114,52,116, - 0,160,1,100,2,116,2,161,2,1,0,124,2,100,1,107, - 9,114,40,100,3,125,3,116,3,124,3,131,1,130,1,124, - 1,114,48,100,4,110,2,100,5,125,2,116,4,160,5,124, - 0,161,1,125,0,116,6,124,0,131,1,92,2,125,4,125, - 5,124,5,160,7,100,6,161,1,92,3,125,6,125,7,125, - 8,116,8,106,9,106,10,125,9,124,9,100,1,107,8,114, - 114,116,11,100,7,131,1,130,1,100,4,160,12,124,6,114, - 126,124,6,110,2,124,8,124,7,124,9,103,3,161,1,125, - 10,124,2,100,1,107,8,114,172,116,8,106,13,106,14,100, - 8,107,2,114,164,100,4,125,2,110,8,116,8,106,13,106, - 14,125,2,116,15,124,2,131,1,125,2,124,2,100,4,107, - 3,114,224,124,2,160,16,161,0,115,210,116,17,100,9,160, - 18,124,2,161,1,131,1,130,1,100,10,160,18,124,10,116, - 19,124,2,161,3,125,10,116,20,124,4,116,21,124,10,116, - 22,100,8,25,0,23,0,131,3,83,0,41,11,97,254,2, - 0,0,71,105,118,101,110,32,116,104,101,32,112,97,116,104, - 32,116,111,32,97,32,46,112,121,32,102,105,108,101,44,32, - 114,101,116,117,114,110,32,116,104,101,32,112,97,116,104,32, - 116,111,32,105,116,115,32,46,112,121,99,32,102,105,108,101, - 46,10,10,32,32,32,32,84,104,101,32,46,112,121,32,102, - 105,108,101,32,100,111,101,115,32,110,111,116,32,110,101,101, - 100,32,116,111,32,101,120,105,115,116,59,32,116,104,105,115, - 32,115,105,109,112,108,121,32,114,101,116,117,114,110,115,32, - 116,104,101,32,112,97,116,104,32,116,111,32,116,104,101,10, - 32,32,32,32,46,112,121,99,32,102,105,108,101,32,99,97, - 108,99,117,108,97,116,101,100,32,97,115,32,105,102,32,116, - 104,101,32,46,112,121,32,102,105,108,101,32,119,101,114,101, - 32,105,109,112,111,114,116,101,100,46,10,10,32,32,32,32, - 84,104,101,32,39,111,112,116,105,109,105,122,97,116,105,111, - 110,39,32,112,97,114,97,109,101,116,101,114,32,99,111,110, - 116,114,111,108,115,32,116,104,101,32,112,114,101,115,117,109, - 101,100,32,111,112,116,105,109,105,122,97,116,105,111,110,32, - 108,101,118,101,108,32,111,102,10,32,32,32,32,116,104,101, - 32,98,121,116,101,99,111,100,101,32,102,105,108,101,46,32, - 73,102,32,39,111,112,116,105,109,105,122,97,116,105,111,110, - 39,32,105,115,32,110,111,116,32,78,111,110,101,44,32,116, - 104,101,32,115,116,114,105,110,103,32,114,101,112,114,101,115, - 101,110,116,97,116,105,111,110,10,32,32,32,32,111,102,32, - 116,104,101,32,97,114,103,117,109,101,110,116,32,105,115,32, - 116,97,107,101,110,32,97,110,100,32,118,101,114,105,102,105, - 101,100,32,116,111,32,98,101,32,97,108,112,104,97,110,117, - 109,101,114,105,99,32,40,101,108,115,101,32,86,97,108,117, - 101,69,114,114,111,114,10,32,32,32,32,105,115,32,114,97, - 105,115,101,100,41,46,10,10,32,32,32,32,84,104,101,32, - 100,101,98,117,103,95,111,118,101,114,114,105,100,101,32,112, - 97,114,97,109,101,116,101,114,32,105,115,32,100,101,112,114, - 101,99,97,116,101,100,46,32,73,102,32,100,101,98,117,103, - 95,111,118,101,114,114,105,100,101,32,105,115,32,110,111,116, - 32,78,111,110,101,44,10,32,32,32,32,97,32,84,114,117, - 101,32,118,97,108,117,101,32,105,115,32,116,104,101,32,115, - 97,109,101,32,97,115,32,115,101,116,116,105,110,103,32,39, - 111,112,116,105,109,105,122,97,116,105,111,110,39,32,116,111, - 32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110, - 103,10,32,32,32,32,119,104,105,108,101,32,97,32,70,97, - 108,115,101,32,118,97,108,117,101,32,105,115,32,101,113,117, - 105,118,97,108,101,110,116,32,116,111,32,115,101,116,116,105, + 115,105,116,105,118,101,108,121,46,70,114,2,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,5,0,0,0,41,0,0,0,115,2,0,0, + 0,0,2,41,5,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,218,35,95, + 67,65,83,69,95,73,78,83,69,78,83,73,84,73,86,69, + 95,80,76,65,84,70,79,82,77,83,95,83,84,82,95,75, + 69,89,41,1,114,5,0,0,0,114,2,0,0,0,41,1, + 114,3,0,0,0,114,4,0,0,0,218,16,95,109,97,107, + 101,95,114,101,108,97,120,95,99,97,115,101,30,0,0,0, + 115,14,0,0,0,0,1,12,1,12,1,6,2,4,2,14, + 4,8,3,114,11,0,0,0,99,1,0,0,0,0,0,0, + 0,1,0,0,0,4,0,0,0,67,0,0,0,115,20,0, + 0,0,116,0,124,0,131,1,100,1,64,0,160,1,100,2, + 100,3,161,2,83,0,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,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,7,95,119,95,108,111,110,103,47,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,4,0,0,0,67,0,0,0,115, + 12,0,0,0,116,0,160,1,124,0,100,1,161,2,83,0, + 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,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,7,95,114,95,108,111,110,103, + 52,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,4,0,0, + 0,71,0,0,0,115,20,0,0,0,116,0,160,1,100,1, + 100,2,132,0,124,0,68,0,131,1,161,1,83,0,41,3, + 122,31,82,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,5,0, + 0,0,83,0,0,0,115,26,0,0,0,103,0,124,0,93, + 18,125,1,124,1,114,4,124,1,160,0,116,1,161,1,145, + 2,113,4,83,0,114,2,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,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 250,10,60,108,105,115,116,99,111,109,112,62,59,0,0,0, + 115,2,0,0,0,6,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,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,218,10,95,112,97,116,104,95,106,111, + 105,110,57,0,0,0,115,4,0,0,0,0,2,10,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,96,0,0,0,116,0, + 116,1,131,1,100,1,107,2,114,36,124,0,160,2,116,3, + 161,1,92,3,125,1,125,2,125,3,124,1,124,3,102,2, + 83,0,120,50,116,4,124,0,131,1,68,0,93,38,125,4, + 124,4,116,1,107,6,114,46,124,0,106,5,124,4,100,1, + 100,2,141,2,92,2,125,1,125,3,124,1,124,3,102,2, + 83,0,113,46,87,0,100,3,124,0,102,2,83,0,41,4, + 122,32,82,101,112,108,97,99,101,109,101,110,116,32,102,111, + 114,32,111,115,46,112,97,116,104,46,115,112,108,105,116,40, + 41,46,233,1,0,0,0,41,1,90,8,109,97,120,115,112, + 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,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,11,95,112,97,116,104,95,115,112,108,105,116,63,0,0, + 0,115,16,0,0,0,0,2,12,1,16,1,8,1,14,1, + 8,1,18,1,12,1,114,38,0,0,0,99,1,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 115,10,0,0,0,116,0,160,1,124,0,161,1,83,0,41, + 1,122,126,83,116,97,116,32,116,104,101,32,112,97,116,104, + 46,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,1,0,0,0,90,4,115,116,97,116,41,1, + 114,35,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,218,10,95,112,97,116,104,95,115,116,97,116, + 75,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,48,0,0,0,121,12,116,0,124,0, + 131,1,125,2,87,0,110,20,4,0,116,1,107,10,114,32, + 1,0,1,0,1,0,100,1,83,0,88,0,124,2,106,2, + 100,2,64,0,124,1,107,2,83,0,41,3,122,49,84,101, + 115,116,32,119,104,101,116,104,101,114,32,116,104,101,32,112, + 97,116,104,32,105,115,32,116,104,101,32,115,112,101,99,105, + 102,105,101,100,32,109,111,100,101,32,116,121,112,101,46,70, + 105,0,240,0,0,41,3,114,39,0,0,0,218,7,79,83, + 69,114,114,111,114,218,7,115,116,95,109,111,100,101,41,3, + 114,35,0,0,0,218,4,109,111,100,101,90,9,115,116,97, + 116,95,105,110,102,111,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,18,95,112,97,116,104,95,105,115,95, + 109,111,100,101,95,116,121,112,101,85,0,0,0,115,10,0, + 0,0,0,2,2,1,12,1,14,1,6,1,114,43,0,0, + 0,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, + 0,0,67,0,0,0,115,10,0,0,0,116,0,124,0,100, + 1,131,2,83,0,41,2,122,31,82,101,112,108,97,99,101, + 109,101,110,116,32,102,111,114,32,111,115,46,112,97,116,104, + 46,105,115,102,105,108,101,46,105,0,128,0,0,41,1,114, + 43,0,0,0,41,1,114,35,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,218,12,95,112,97,116, + 104,95,105,115,102,105,108,101,94,0,0,0,115,2,0,0, + 0,0,2,114,44,0,0,0,99,1,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,67,0,0,0,115,22,0, + 0,0,124,0,115,12,116,0,160,1,161,0,125,0,116,2, + 124,0,100,1,131,2,83,0,41,2,122,30,82,101,112,108, + 97,99,101,109,101,110,116,32,102,111,114,32,111,115,46,112, + 97,116,104,46,105,115,100,105,114,46,105,0,64,0,0,41, + 3,114,1,0,0,0,218,6,103,101,116,99,119,100,114,43, + 0,0,0,41,1,114,35,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,218,11,95,112,97,116,104, + 95,105,115,100,105,114,99,0,0,0,115,6,0,0,0,0, + 2,4,1,8,1,114,46,0,0,0,233,182,1,0,0,99, + 3,0,0,0,0,0,0,0,6,0,0,0,17,0,0,0, + 67,0,0,0,115,162,0,0,0,100,1,160,0,124,0,116, + 1,124,0,131,1,161,2,125,3,116,2,160,3,124,3,116, + 2,106,4,116,2,106,5,66,0,116,2,106,6,66,0,124, + 2,100,2,64,0,161,3,125,4,121,50,116,7,160,8,124, + 4,100,3,161,2,143,16,125,5,124,5,160,9,124,1,161, + 1,1,0,87,0,100,4,81,0,82,0,88,0,116,2,160, + 10,124,3,124,0,161,2,1,0,87,0,110,58,4,0,116, + 11,107,10,114,156,1,0,1,0,1,0,121,14,116,2,160, + 12,124,3,161,1,1,0,87,0,110,20,4,0,116,11,107, + 10,114,148,1,0,1,0,1,0,89,0,110,2,88,0,130, + 0,89,0,110,2,88,0,100,4,83,0,41,5,122,162,66, + 101,115,116,45,101,102,102,111,114,116,32,102,117,110,99,116, + 105,111,110,32,116,111,32,119,114,105,116,101,32,100,97,116, + 97,32,116,111,32,97,32,112,97,116,104,32,97,116,111,109, + 105,99,97,108,108,121,46,10,32,32,32,32,66,101,32,112, + 114,101,112,97,114,101,100,32,116,111,32,104,97,110,100,108, + 101,32,97,32,70,105,108,101,69,120,105,115,116,115,69,114, + 114,111,114,32,105,102,32,99,111,110,99,117,114,114,101,110, + 116,32,119,114,105,116,105,110,103,32,111,102,32,116,104,101, + 10,32,32,32,32,116,101,109,112,111,114,97,114,121,32,102, + 105,108,101,32,105,115,32,97,116,116,101,109,112,116,101,100, + 46,122,5,123,125,46,123,125,105,182,1,0,0,90,2,119, + 98,78,41,13,218,6,102,111,114,109,97,116,218,2,105,100, + 114,1,0,0,0,90,4,111,112,101,110,90,6,79,95,69, + 88,67,76,90,7,79,95,67,82,69,65,84,90,8,79,95, + 87,82,79,78,76,89,218,3,95,105,111,218,6,70,105,108, + 101,73,79,218,5,119,114,105,116,101,218,7,114,101,112,108, + 97,99,101,114,40,0,0,0,90,6,117,110,108,105,110,107, + 41,6,114,35,0,0,0,218,4,100,97,116,97,114,42,0, + 0,0,90,8,112,97,116,104,95,116,109,112,90,2,102,100, + 218,4,102,105,108,101,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,13,95,119,114,105,116,101,95,97,116, + 111,109,105,99,106,0,0,0,115,26,0,0,0,0,5,16, + 1,6,1,26,1,2,3,14,1,20,1,16,1,14,1,2, + 1,14,1,14,1,6,1,114,56,0,0,0,105,64,13,0, + 0,233,2,0,0,0,114,13,0,0,0,115,2,0,0,0, + 13,10,90,11,95,95,112,121,99,97,99,104,101,95,95,122, + 4,111,112,116,45,122,3,46,112,121,122,4,46,112,121,99, + 78,41,1,218,12,111,112,116,105,109,105,122,97,116,105,111, + 110,99,2,0,0,0,1,0,0,0,11,0,0,0,6,0, + 0,0,67,0,0,0,115,244,0,0,0,124,1,100,1,107, + 9,114,52,116,0,160,1,100,2,116,2,161,2,1,0,124, + 2,100,1,107,9,114,40,100,3,125,3,116,3,124,3,131, + 1,130,1,124,1,114,48,100,4,110,2,100,5,125,2,116, + 4,160,5,124,0,161,1,125,0,116,6,124,0,131,1,92, + 2,125,4,125,5,124,5,160,7,100,6,161,1,92,3,125, + 6,125,7,125,8,116,8,106,9,106,10,125,9,124,9,100, + 1,107,8,114,114,116,11,100,7,131,1,130,1,100,4,160, + 12,124,6,114,126,124,6,110,2,124,8,124,7,124,9,103, + 3,161,1,125,10,124,2,100,1,107,8,114,172,116,8,106, + 13,106,14,100,8,107,2,114,164,100,4,125,2,110,8,116, + 8,106,13,106,14,125,2,116,15,124,2,131,1,125,2,124, + 2,100,4,107,3,114,224,124,2,160,16,161,0,115,210,116, + 17,100,9,160,18,124,2,161,1,131,1,130,1,100,10,160, + 18,124,10,116,19,124,2,161,3,125,10,116,20,124,4,116, + 21,124,10,116,22,100,8,25,0,23,0,131,3,83,0,41, + 11,97,254,2,0,0,71,105,118,101,110,32,116,104,101,32, + 112,97,116,104,32,116,111,32,97,32,46,112,121,32,102,105, + 108,101,44,32,114,101,116,117,114,110,32,116,104,101,32,112, + 97,116,104,32,116,111,32,105,116,115,32,46,112,121,99,32, + 102,105,108,101,46,10,10,32,32,32,32,84,104,101,32,46, + 112,121,32,102,105,108,101,32,100,111,101,115,32,110,111,116, + 32,110,101,101,100,32,116,111,32,101,120,105,115,116,59,32, + 116,104,105,115,32,115,105,109,112,108,121,32,114,101,116,117, + 114,110,115,32,116,104,101,32,112,97,116,104,32,116,111,32, + 116,104,101,10,32,32,32,32,46,112,121,99,32,102,105,108, + 101,32,99,97,108,99,117,108,97,116,101,100,32,97,115,32, + 105,102,32,116,104,101,32,46,112,121,32,102,105,108,101,32, + 119,101,114,101,32,105,109,112,111,114,116,101,100,46,10,10, + 32,32,32,32,84,104,101,32,39,111,112,116,105,109,105,122, + 97,116,105,111,110,39,32,112,97,114,97,109,101,116,101,114, + 32,99,111,110,116,114,111,108,115,32,116,104,101,32,112,114, + 101,115,117,109,101,100,32,111,112,116,105,109,105,122,97,116, + 105,111,110,32,108,101,118,101,108,32,111,102,10,32,32,32, + 32,116,104,101,32,98,121,116,101,99,111,100,101,32,102,105, + 108,101,46,32,73,102,32,39,111,112,116,105,109,105,122,97, + 116,105,111,110,39,32,105,115,32,110,111,116,32,78,111,110, + 101,44,32,116,104,101,32,115,116,114,105,110,103,32,114,101, + 112,114,101,115,101,110,116,97,116,105,111,110,10,32,32,32, + 32,111,102,32,116,104,101,32,97,114,103,117,109,101,110,116, + 32,105,115,32,116,97,107,101,110,32,97,110,100,32,118,101, + 114,105,102,105,101,100,32,116,111,32,98,101,32,97,108,112, + 104,97,110,117,109,101,114,105,99,32,40,101,108,115,101,32, + 86,97,108,117,101,69,114,114,111,114,10,32,32,32,32,105, + 115,32,114,97,105,115,101,100,41,46,10,10,32,32,32,32, + 84,104,101,32,100,101,98,117,103,95,111,118,101,114,114,105, + 100,101,32,112,97,114,97,109,101,116,101,114,32,105,115,32, + 100,101,112,114,101,99,97,116,101,100,46,32,73,102,32,100, + 101,98,117,103,95,111,118,101,114,114,105,100,101,32,105,115, + 32,110,111,116,32,78,111,110,101,44,10,32,32,32,32,97, + 32,84,114,117,101,32,118,97,108,117,101,32,105,115,32,116, + 104,101,32,115,97,109,101,32,97,115,32,115,101,116,116,105, 110,103,32,39,111,112,116,105,109,105,122,97,116,105,111,110, - 39,32,116,111,32,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,32,0, - 0,0,114,31,0,0,0,218,1,46,122,36,115,121,115,46, - 105,109,112,108,101,109,101,110,116,97,116,105,111,110,46,99, - 97,99,104,101,95,116,97,103,32,105,115,32,78,111,110,101, - 233,0,0,0,0,122,24,123,33,114,125,32,105,115,32,110, - 111,116,32,97,108,112,104,97,110,117,109,101,114,105,99,122, - 7,123,125,46,123,125,123,125,41,23,218,9,95,119,97,114, - 110,105,110,103,115,218,4,119,97,114,110,218,18,68,101,112, - 114,101,99,97,116,105,111,110,87,97,114,110,105,110,103,218, - 9,84,121,112,101,69,114,114,111,114,114,3,0,0,0,218, - 6,102,115,112,97,116,104,114,40,0,0,0,114,34,0,0, - 0,114,8,0,0,0,218,14,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,218,9,99,97,99,104,101,95,116,97, - 103,218,19,78,111,116,73,109,112,108,101,109,101,110,116,101, - 100,69,114,114,111,114,114,28,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,50,0,0,0,218,4,95,79,80, - 84,114,30,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,37,0,0,0,90,14,100,101,98,117, - 103,95,111,118,101,114,114,105,100,101,114,60,0,0,0,218, - 7,109,101,115,115,97,103,101,218,4,104,101,97,100,114,39, - 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,6,0,0,0,218,17,99,97,99,104,101, - 95,102,114,111,109,95,115,111,117,114,99,101,10,1,0,0, - 115,48,0,0,0,0,18,8,1,6,1,6,1,8,1,4, - 1,8,1,12,1,10,1,12,1,16,1,8,1,8,1,8, - 1,24,1,8,1,12,1,6,2,8,1,8,1,8,1,8, - 1,14,1,14,1,114,83,0,0,0,99,1,0,0,0,0, - 0,0,0,8,0,0,0,5,0,0,0,67,0,0,0,115, - 230,0,0,0,116,0,106,1,106,2,100,1,107,8,114,20, - 116,3,100,2,131,1,130,1,116,4,160,5,124,0,161,1, - 125,0,116,6,124,0,131,1,92,2,125,1,125,2,116,6, - 124,1,131,1,92,2,125,1,125,3,124,3,116,7,107,3, - 114,78,116,8,100,3,160,9,116,7,124,0,161,2,131,1, - 130,1,124,2,160,10,100,4,161,1,125,4,124,4,100,11, - 107,7,114,112,116,8,100,7,160,9,124,2,161,1,131,1, - 130,1,110,86,124,4,100,6,107,2,114,198,124,2,160,11, - 100,4,100,5,161,2,100,12,25,0,125,5,124,5,160,12, - 116,13,161,1,115,160,116,8,100,8,160,9,116,13,161,1, - 131,1,130,1,124,5,116,14,116,13,131,1,100,1,133,2, - 25,0,125,6,124,6,160,15,161,0,115,198,116,8,100,9, - 160,9,124,5,161,1,131,1,130,1,124,2,160,16,100,4, - 161,1,100,10,25,0,125,7,116,17,124,1,124,7,116,18, - 100,10,25,0,23,0,131,2,83,0,41,13,97,110,1,0, - 0,71,105,118,101,110,32,116,104,101,32,112,97,116,104,32, - 116,111,32,97,32,46,112,121,99,46,32,102,105,108,101,44, - 32,114,101,116,117,114,110,32,116,104,101,32,112,97,116,104, - 32,116,111,32,105,116,115,32,46,112,121,32,102,105,108,101, - 46,10,10,32,32,32,32,84,104,101,32,46,112,121,99,32, - 102,105,108,101,32,100,111,101,115,32,110,111,116,32,110,101, - 101,100,32,116,111,32,101,120,105,115,116,59,32,116,104,105, - 115,32,115,105,109,112,108,121,32,114,101,116,117,114,110,115, - 32,116,104,101,32,112,97,116,104,32,116,111,10,32,32,32, - 32,116,104,101,32,46,112,121,32,102,105,108,101,32,99,97, - 108,99,117,108,97,116,101,100,32,116,111,32,99,111,114,114, - 101,115,112,111,110,100,32,116,111,32,116,104,101,32,46,112, - 121,99,32,102,105,108,101,46,32,32,73,102,32,112,97,116, - 104,32,100,111,101,115,10,32,32,32,32,110,111,116,32,99, - 111,110,102,111,114,109,32,116,111,32,80,69,80,32,51,49, - 52,55,47,52,56,56,32,102,111,114,109,97,116,44,32,86, - 97,108,117,101,69,114,114,111,114,32,119,105,108,108,32,98, - 101,32,114,97,105,115,101,100,46,32,73,102,10,32,32,32, - 32,115,121,115,46,105,109,112,108,101,109,101,110,116,97,116, - 105,111,110,46,99,97,99,104,101,95,116,97,103,32,105,115, - 32,78,111,110,101,32,116,104,101,110,32,78,111,116,73,109, - 112,108,101,109,101,110,116,101,100,69,114,114,111,114,32,105, + 39,32,116,111,32,116,104,101,32,101,109,112,116,121,32,115, + 116,114,105,110,103,10,32,32,32,32,119,104,105,108,101,32, + 97,32,70,97,108,115,101,32,118,97,108,117,101,32,105,115, + 32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115, + 101,116,116,105,110,103,32,39,111,112,116,105,109,105,122,97, + 116,105,111,110,39,32,116,111,32,39,49,39,46,10,10,32, + 32,32,32,73,102,32,115,121,115,46,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,46,99,97,99,104,101,95,116, + 97,103,32,105,115,32,78,111,110,101,32,116,104,101,110,32, + 78,111,116,73,109,112,108,101,109,101,110,116,101,100,69,114, + 114,111,114,32,105,115,32,114,97,105,115,101,100,46,10,10, + 32,32,32,32,78,122,70,116,104,101,32,100,101,98,117,103, + 95,111,118,101,114,114,105,100,101,32,112,97,114,97,109,101, + 116,101,114,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,59,32,117,115,101,32,39,111,112,116,105,109,105,122,97, + 116,105,111,110,39,32,105,110,115,116,101,97,100,122,50,100, + 101,98,117,103,95,111,118,101,114,114,105,100,101,32,111,114, + 32,111,112,116,105,109,105,122,97,116,105,111,110,32,109,117, + 115,116,32,98,101,32,115,101,116,32,116,111,32,78,111,110, + 101,114,30,0,0,0,114,29,0,0,0,218,1,46,122,36, + 115,121,115,46,105,109,112,108,101,109,101,110,116,97,116,105, + 111,110,46,99,97,99,104,101,95,116,97,103,32,105,115,32, + 78,111,110,101,233,0,0,0,0,122,24,123,33,114,125,32, + 105,115,32,110,111,116,32,97,108,112,104,97,110,117,109,101, + 114,105,99,122,7,123,125,46,123,125,123,125,41,23,218,9, + 95,119,97,114,110,105,110,103,115,218,4,119,97,114,110,218, + 18,68,101,112,114,101,99,97,116,105,111,110,87,97,114,110, + 105,110,103,218,9,84,121,112,101,69,114,114,111,114,114,1, + 0,0,0,218,6,102,115,112,97,116,104,114,38,0,0,0, + 114,32,0,0,0,114,6,0,0,0,218,14,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,218,9,99,97,99,104, + 101,95,116,97,103,218,19,78,111,116,73,109,112,108,101,109, + 101,110,116,101,100,69,114,114,111,114,114,26,0,0,0,218, + 5,102,108,97,103,115,218,8,111,112,116,105,109,105,122,101, + 218,3,115,116,114,218,7,105,115,97,108,110,117,109,218,10, + 86,97,108,117,101,69,114,114,111,114,114,48,0,0,0,218, + 4,95,79,80,84,114,28,0,0,0,218,8,95,80,89,67, + 65,67,72,69,218,17,66,89,84,69,67,79,68,69,95,83, + 85,70,70,73,88,69,83,41,11,114,35,0,0,0,90,14, + 100,101,98,117,103,95,111,118,101,114,114,105,100,101,114,58, + 0,0,0,218,7,109,101,115,115,97,103,101,218,4,104,101, + 97,100,114,37,0,0,0,90,4,98,97,115,101,218,3,115, + 101,112,218,4,114,101,115,116,90,3,116,97,103,90,15,97, + 108,109,111,115,116,95,102,105,108,101,110,97,109,101,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,218,17,99, + 97,99,104,101,95,102,114,111,109,95,115,111,117,114,99,101, + 10,1,0,0,115,48,0,0,0,0,18,8,1,6,1,6, + 1,8,1,4,1,8,1,12,1,10,1,12,1,16,1,8, + 1,8,1,8,1,24,1,8,1,12,1,6,2,8,1,8, + 1,8,1,8,1,14,1,14,1,114,81,0,0,0,99,1, + 0,0,0,0,0,0,0,8,0,0,0,5,0,0,0,67, + 0,0,0,115,230,0,0,0,116,0,106,1,106,2,100,1, + 107,8,114,20,116,3,100,2,131,1,130,1,116,4,160,5, + 124,0,161,1,125,0,116,6,124,0,131,1,92,2,125,1, + 125,2,116,6,124,1,131,1,92,2,125,1,125,3,124,3, + 116,7,107,3,114,78,116,8,100,3,160,9,116,7,124,0, + 161,2,131,1,130,1,124,2,160,10,100,4,161,1,125,4, + 124,4,100,5,107,7,114,112,116,8,100,6,160,9,124,2, + 161,1,131,1,130,1,110,86,124,4,100,7,107,2,114,198, + 124,2,160,11,100,4,100,8,161,2,100,9,25,0,125,5, + 124,5,160,12,116,13,161,1,115,160,116,8,100,10,160,9, + 116,13,161,1,131,1,130,1,124,5,116,14,116,13,131,1, + 100,1,133,2,25,0,125,6,124,6,160,15,161,0,115,198, + 116,8,100,11,160,9,124,5,161,1,131,1,130,1,124,2, + 160,16,100,4,161,1,100,12,25,0,125,7,116,17,124,1, + 124,7,116,18,100,12,25,0,23,0,131,2,83,0,41,13, + 97,110,1,0,0,71,105,118,101,110,32,116,104,101,32,112, + 97,116,104,32,116,111,32,97,32,46,112,121,99,46,32,102, + 105,108,101,44,32,114,101,116,117,114,110,32,116,104,101,32, + 112,97,116,104,32,116,111,32,105,116,115,32,46,112,121,32, + 102,105,108,101,46,10,10,32,32,32,32,84,104,101,32,46, + 112,121,99,32,102,105,108,101,32,100,111,101,115,32,110,111, + 116,32,110,101,101,100,32,116,111,32,101,120,105,115,116,59, + 32,116,104,105,115,32,115,105,109,112,108,121,32,114,101,116, + 117,114,110,115,32,116,104,101,32,112,97,116,104,32,116,111, + 10,32,32,32,32,116,104,101,32,46,112,121,32,102,105,108, + 101,32,99,97,108,99,117,108,97,116,101,100,32,116,111,32, + 99,111,114,114,101,115,112,111,110,100,32,116,111,32,116,104, + 101,32,46,112,121,99,32,102,105,108,101,46,32,32,73,102, + 32,112,97,116,104,32,100,111,101,115,10,32,32,32,32,110, + 111,116,32,99,111,110,102,111,114,109,32,116,111,32,80,69, + 80,32,51,49,52,55,47,52,56,56,32,102,111,114,109,97, + 116,44,32,86,97,108,117,101,69,114,114,111,114,32,119,105, + 108,108,32,98,101,32,114,97,105,115,101,100,46,32,73,102, + 10,32,32,32,32,115,121,115,46,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,46,99,97,99,104,101,95,116,97, + 103,32,105,115,32,78,111,110,101,32,116,104,101,110,32,78, + 111,116,73,109,112,108,101,109,101,110,116,101,100,69,114,114, + 111,114,32,105,115,32,114,97,105,115,101,100,46,10,10,32, + 32,32,32,78,122,36,115,121,115,46,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,46,99,97,99,104,101,95,116, + 97,103,32,105,115,32,78,111,110,101,122,37,123,125,32,110, + 111,116,32,98,111,116,116,111,109,45,108,101,118,101,108,32, + 100,105,114,101,99,116,111,114,121,32,105,110,32,123,33,114, + 125,114,59,0,0,0,62,2,0,0,0,114,57,0,0,0, + 233,3,0,0,0,122,33,101,120,112,101,99,116,101,100,32, + 111,110,108,121,32,50,32,111,114,32,51,32,100,111,116,115, + 32,105,110,32,123,33,114,125,114,82,0,0,0,114,57,0, + 0,0,233,254,255,255,255,122,57,111,112,116,105,109,105,122, + 97,116,105,111,110,32,112,111,114,116,105,111,110,32,111,102, + 32,102,105,108,101,110,97,109,101,32,100,111,101,115,32,110, + 111,116,32,115,116,97,114,116,32,119,105,116,104,32,123,33, + 114,125,122,52,111,112,116,105,109,105,122,97,116,105,111,110, + 32,108,101,118,101,108,32,123,33,114,125,32,105,115,32,110, + 111,116,32,97,110,32,97,108,112,104,97,110,117,109,101,114, + 105,99,32,118,97,108,117,101,114,60,0,0,0,41,19,114, + 6,0,0,0,114,66,0,0,0,114,67,0,0,0,114,68, + 0,0,0,114,1,0,0,0,114,65,0,0,0,114,38,0, + 0,0,114,75,0,0,0,114,73,0,0,0,114,48,0,0, + 0,218,5,99,111,117,110,116,114,34,0,0,0,114,8,0, + 0,0,114,74,0,0,0,114,31,0,0,0,114,72,0,0, + 0,218,9,112,97,114,116,105,116,105,111,110,114,28,0,0, + 0,218,15,83,79,85,82,67,69,95,83,85,70,70,73,88, + 69,83,41,8,114,35,0,0,0,114,78,0,0,0,90,16, + 112,121,99,97,99,104,101,95,102,105,108,101,110,97,109,101, + 90,7,112,121,99,97,99,104,101,90,9,100,111,116,95,99, + 111,117,110,116,114,58,0,0,0,90,9,111,112,116,95,108, + 101,118,101,108,90,13,98,97,115,101,95,102,105,108,101,110, + 97,109,101,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,17,115,111,117,114,99,101,95,102,114,111,109,95, + 99,97,99,104,101,55,1,0,0,115,46,0,0,0,0,9, + 12,1,8,1,10,1,12,1,12,1,8,1,6,1,10,1, + 10,1,8,1,6,1,10,1,8,1,16,1,10,1,6,1, + 8,1,16,1,8,1,6,1,8,1,14,1,114,87,0,0, + 0,99,1,0,0,0,0,0,0,0,5,0,0,0,12,0, + 0,0,67,0,0,0,115,126,0,0,0,116,0,124,0,131, + 1,100,1,107,2,114,16,100,2,83,0,124,0,160,1,100, + 3,161,1,92,3,125,1,125,2,125,3,124,1,114,56,124, + 3,160,2,161,0,100,4,100,5,133,2,25,0,100,6,107, + 3,114,60,124,0,83,0,121,12,116,3,124,0,131,1,125, + 4,87,0,110,36,4,0,116,4,116,5,102,2,107,10,114, + 108,1,0,1,0,1,0,124,0,100,2,100,5,133,2,25, + 0,125,4,89,0,110,2,88,0,116,6,124,4,131,1,114, + 122,124,4,83,0,124,0,83,0,41,7,122,188,67,111,110, + 118,101,114,116,32,97,32,98,121,116,101,99,111,100,101,32, + 102,105,108,101,32,112,97,116,104,32,116,111,32,97,32,115, + 111,117,114,99,101,32,112,97,116,104,32,40,105,102,32,112, + 111,115,115,105,98,108,101,41,46,10,10,32,32,32,32,84, + 104,105,115,32,102,117,110,99,116,105,111,110,32,101,120,105, + 115,116,115,32,112,117,114,101,108,121,32,102,111,114,32,98, + 97,99,107,119,97,114,100,115,45,99,111,109,112,97,116,105, + 98,105,108,105,116,121,32,102,111,114,10,32,32,32,32,80, + 121,73,109,112,111,114,116,95,69,120,101,99,67,111,100,101, + 77,111,100,117,108,101,87,105,116,104,70,105,108,101,110,97, + 109,101,115,40,41,32,105,110,32,116,104,101,32,67,32,65, + 80,73,46,10,10,32,32,32,32,114,60,0,0,0,78,114, + 59,0,0,0,233,253,255,255,255,233,255,255,255,255,90,2, + 112,121,41,7,114,31,0,0,0,114,32,0,0,0,218,5, + 108,111,119,101,114,114,87,0,0,0,114,68,0,0,0,114, + 73,0,0,0,114,44,0,0,0,41,5,218,13,98,121,116, + 101,99,111,100,101,95,112,97,116,104,114,80,0,0,0,114, + 36,0,0,0,90,9,101,120,116,101,110,115,105,111,110,218, + 11,115,111,117,114,99,101,95,112,97,116,104,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,15,95,103,101, + 116,95,115,111,117,114,99,101,102,105,108,101,89,1,0,0, + 115,20,0,0,0,0,7,12,1,4,1,16,1,24,1,4, + 1,2,1,12,1,18,1,18,1,114,93,0,0,0,99,1, + 0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,67, + 0,0,0,115,72,0,0,0,124,0,160,0,116,1,116,2, + 131,1,161,1,114,46,121,8,116,3,124,0,131,1,83,0, + 4,0,116,4,107,10,114,42,1,0,1,0,1,0,89,0, + 113,68,88,0,110,22,124,0,160,0,116,1,116,5,131,1, + 161,1,114,64,124,0,83,0,100,0,83,0,100,0,83,0, + 41,1,78,41,6,218,8,101,110,100,115,119,105,116,104,218, + 5,116,117,112,108,101,114,86,0,0,0,114,81,0,0,0, + 114,68,0,0,0,114,76,0,0,0,41,1,218,8,102,105, + 108,101,110,97,109,101,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,11,95,103,101,116,95,99,97,99,104, + 101,100,108,1,0,0,115,16,0,0,0,0,1,14,1,2, + 1,8,1,14,1,8,1,14,1,4,2,114,97,0,0,0, + 99,1,0,0,0,0,0,0,0,2,0,0,0,11,0,0, + 0,67,0,0,0,115,52,0,0,0,121,14,116,0,124,0, + 131,1,106,1,125,1,87,0,110,24,4,0,116,2,107,10, + 114,38,1,0,1,0,1,0,100,1,125,1,89,0,110,2, + 88,0,124,1,100,2,79,0,125,1,124,1,83,0,41,3, + 122,51,67,97,108,99,117,108,97,116,101,32,116,104,101,32, + 109,111,100,101,32,112,101,114,109,105,115,115,105,111,110,115, + 32,102,111,114,32,97,32,98,121,116,101,99,111,100,101,32, + 102,105,108,101,46,105,182,1,0,0,233,128,0,0,0,41, + 3,114,39,0,0,0,114,41,0,0,0,114,40,0,0,0, + 41,2,114,35,0,0,0,114,42,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,10,95,99,97, + 108,99,95,109,111,100,101,120,1,0,0,115,12,0,0,0, + 0,2,2,1,14,1,14,1,10,3,8,1,114,99,0,0, + 0,99,1,0,0,0,0,0,0,0,3,0,0,0,11,0, + 0,0,3,0,0,0,115,68,0,0,0,100,6,135,0,102, + 1,100,2,100,3,132,9,125,1,121,10,116,0,106,1,125, + 2,87,0,110,28,4,0,116,2,107,10,114,52,1,0,1, + 0,1,0,100,4,100,5,132,0,125,2,89,0,110,2,88, + 0,124,2,124,1,136,0,131,2,1,0,124,1,83,0,41, + 7,122,252,68,101,99,111,114,97,116,111,114,32,116,111,32, + 118,101,114,105,102,121,32,116,104,97,116,32,116,104,101,32, + 109,111,100,117,108,101,32,98,101,105,110,103,32,114,101,113, + 117,101,115,116,101,100,32,109,97,116,99,104,101,115,32,116, + 104,101,32,111,110,101,32,116,104,101,10,32,32,32,32,108, + 111,97,100,101,114,32,99,97,110,32,104,97,110,100,108,101, + 46,10,10,32,32,32,32,84,104,101,32,102,105,114,115,116, + 32,97,114,103,117,109,101,110,116,32,40,115,101,108,102,41, + 32,109,117,115,116,32,100,101,102,105,110,101,32,95,110,97, + 109,101,32,119,104,105,99,104,32,116,104,101,32,115,101,99, + 111,110,100,32,97,114,103,117,109,101,110,116,32,105,115,10, + 32,32,32,32,99,111,109,112,97,114,101,100,32,97,103,97, + 105,110,115,116,46,32,73,102,32,116,104,101,32,99,111,109, + 112,97,114,105,115,111,110,32,102,97,105,108,115,32,116,104, + 101,110,32,73,109,112,111,114,116,69,114,114,111,114,32,105, 115,32,114,97,105,115,101,100,46,10,10,32,32,32,32,78, - 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,61,0, - 0,0,114,59,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,62,0,0,0,62,2,0,0,0,114,59,0,0,0,114, - 84,0,0,0,233,254,255,255,255,41,19,114,8,0,0,0, - 114,68,0,0,0,114,69,0,0,0,114,70,0,0,0,114, - 3,0,0,0,114,67,0,0,0,114,40,0,0,0,114,77, - 0,0,0,114,75,0,0,0,114,50,0,0,0,218,5,99, - 111,117,110,116,114,36,0,0,0,114,10,0,0,0,114,76, - 0,0,0,114,33,0,0,0,114,74,0,0,0,218,9,112, - 97,114,116,105,116,105,111,110,114,30,0,0,0,218,15,83, - 79,85,82,67,69,95,83,85,70,70,73,88,69,83,41,8, - 114,37,0,0,0,114,80,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,60,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,6,0,0,0,218,17, - 115,111,117,114,99,101,95,102,114,111,109,95,99,97,99,104, - 101,55,1,0,0,115,46,0,0,0,0,9,12,1,8,1, - 10,1,12,1,12,1,8,1,6,1,10,1,10,1,8,1, - 6,1,10,1,8,1,16,1,10,1,6,1,8,1,16,1, - 8,1,6,1,8,1,14,1,114,89,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,126,0,0,0,116,0,124,0,131,1,100,1,107, - 2,114,16,100,2,83,0,124,0,160,1,100,3,161,1,92, - 3,125,1,125,2,125,3,124,1,114,56,124,3,160,2,161, - 0,100,7,100,8,133,2,25,0,100,6,107,3,114,60,124, - 0,83,0,121,12,116,3,124,0,131,1,125,4,87,0,110, - 36,4,0,116,4,116,5,102,2,107,10,114,108,1,0,1, - 0,1,0,124,0,100,2,100,9,133,2,25,0,125,4,89, - 0,110,2,88,0,116,6,124,4,131,1,114,122,124,4,83, - 0,124,0,83,0,41,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,62,0,0,0,78,114,61,0,0,0, - 114,84,0,0,0,114,31,0,0,0,90,2,112,121,233,253, - 255,255,255,233,255,255,255,255,114,91,0,0,0,41,7,114, - 33,0,0,0,114,34,0,0,0,218,5,108,111,119,101,114, - 114,89,0,0,0,114,70,0,0,0,114,75,0,0,0,114, - 46,0,0,0,41,5,218,13,98,121,116,101,99,111,100,101, - 95,112,97,116,104,114,82,0,0,0,114,38,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,6,0,0,0,218,15,95,103,101,116,95,115,111,117, - 114,99,101,102,105,108,101,89,1,0,0,115,20,0,0,0, - 0,7,12,1,4,1,16,1,24,1,4,1,2,1,12,1, - 18,1,18,1,114,95,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,72, - 0,0,0,124,0,160,0,116,1,116,2,131,1,161,1,114, - 46,121,8,116,3,124,0,131,1,83,0,4,0,116,4,107, - 10,114,42,1,0,1,0,1,0,89,0,113,68,88,0,110, - 22,124,0,160,0,116,1,116,5,131,1,161,1,114,64,124, - 0,83,0,100,0,83,0,100,0,83,0,41,1,78,41,6, - 218,8,101,110,100,115,119,105,116,104,218,5,116,117,112,108, - 101,114,88,0,0,0,114,83,0,0,0,114,70,0,0,0, - 114,78,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,6,0,0,0, - 218,11,95,103,101,116,95,99,97,99,104,101,100,108,1,0, - 0,115,16,0,0,0,0,1,14,1,2,1,8,1,14,1, - 8,1,14,1,4,2,114,99,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,52,0,0,0,121,14,116,0,124,0,131,1,106,1,125, - 1,87,0,110,24,4,0,116,2,107,10,114,38,1,0,1, - 0,1,0,100,1,125,1,89,0,110,2,88,0,124,1,100, - 2,79,0,125,1,124,1,83,0,41,3,122,51,67,97,108, - 99,117,108,97,116,101,32,116,104,101,32,109,111,100,101,32, - 112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32, - 97,32,98,121,116,101,99,111,100,101,32,102,105,108,101,46, - 105,182,1,0,0,233,128,0,0,0,41,3,114,41,0,0, - 0,114,43,0,0,0,114,42,0,0,0,41,2,114,37,0, - 0,0,114,44,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,10,95,99,97,108,99,95,109,111, - 100,101,120,1,0,0,115,12,0,0,0,0,2,2,1,14, - 1,14,1,10,3,8,1,114,101,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,68,0,0,0,100,6,135,0,102,1,100,2,100,3, - 132,9,125,1,121,10,116,0,106,1,125,2,87,0,110,28, - 4,0,116,2,107,10,114,52,1,0,1,0,1,0,100,4, - 100,5,132,0,125,2,89,0,110,2,88,0,124,2,124,1, - 136,0,131,2,1,0,124,1,83,0,41,7,122,252,68,101, - 99,111,114,97,116,111,114,32,116,111,32,118,101,114,105,102, - 121,32,116,104,97,116,32,116,104,101,32,109,111,100,117,108, - 101,32,98,101,105,110,103,32,114,101,113,117,101,115,116,101, - 100,32,109,97,116,99,104,101,115,32,116,104,101,32,111,110, - 101,32,116,104,101,10,32,32,32,32,108,111,97,100,101,114, - 32,99,97,110,32,104,97,110,100,108,101,46,10,10,32,32, - 32,32,84,104,101,32,102,105,114,115,116,32,97,114,103,117, - 109,101,110,116,32,40,115,101,108,102,41,32,109,117,115,116, - 32,100,101,102,105,110,101,32,95,110,97,109,101,32,119,104, - 105,99,104,32,116,104,101,32,115,101,99,111,110,100,32,97, - 114,103,117,109,101,110,116,32,105,115,10,32,32,32,32,99, - 111,109,112,97,114,101,100,32,97,103,97,105,110,115,116,46, - 32,73,102,32,116,104,101,32,99,111,109,112,97,114,105,115, - 111,110,32,102,97,105,108,115,32,116,104,101,110,32,73,109, - 112,111,114,116,69,114,114,111,114,32,105,115,32,114,97,105, - 115,101,100,46,10,10,32,32,32,32,78,99,2,0,0,0, - 0,0,0,0,4,0,0,0,4,0,0,0,31,0,0,0, - 115,66,0,0,0,124,1,100,0,107,8,114,16,124,0,106, - 0,125,1,110,32,124,0,106,0,124,1,107,3,114,48,116, - 1,100,1,124,0,106,0,124,1,102,2,22,0,124,1,100, - 2,141,2,130,1,136,0,124,0,124,1,102,2,124,2,158, - 2,124,3,142,1,83,0,41,3,78,122,30,108,111,97,100, - 101,114,32,102,111,114,32,37,115,32,99,97,110,110,111,116, - 32,104,97,110,100,108,101,32,37,115,41,1,218,4,110,97, - 109,101,41,2,114,102,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,102, - 0,0,0,218,4,97,114,103,115,90,6,107,119,97,114,103, - 115,41,1,218,6,109,101,116,104,111,100,114,4,0,0,0, - 114,6,0,0,0,218,19,95,99,104,101,99,107,95,110,97, - 109,101,95,119,114,97,112,112,101,114,140,1,0,0,115,12, - 0,0,0,0,1,8,1,8,1,10,1,4,1,18,1,122, - 40,95,99,104,101,99,107,95,110,97,109,101,46,60,108,111, - 99,97,108,115,62,46,95,99,104,101,99,107,95,110,97,109, - 101,95,119,114,97,112,112,101,114,99,2,0,0,0,0,0, - 0,0,3,0,0,0,7,0,0,0,83,0,0,0,115,60, - 0,0,0,120,40,100,5,68,0,93,32,125,2,116,0,124, - 1,124,2,131,2,114,6,116,1,124,0,124,2,116,2,124, - 1,124,2,131,2,131,3,1,0,113,6,87,0,124,0,106, - 3,160,4,124,1,106,3,161,1,1,0,100,0,83,0,41, - 6,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, - 4,114,108,0,0,0,114,109,0,0,0,114,110,0,0,0, - 114,111,0,0,0,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,55,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,5,95,119,114,97,112,151,1,0,0,115, - 8,0,0,0,0,1,10,1,10,1,22,1,122,26,95,99, - 104,101,99,107,95,110,97,109,101,46,60,108,111,99,97,108, - 115,62,46,95,119,114,97,112,41,1,78,41,3,218,10,95, - 98,111,111,116,115,116,114,97,112,114,117,0,0,0,218,9, - 78,97,109,101,69,114,114,111,114,41,3,114,106,0,0,0, - 114,107,0,0,0,114,117,0,0,0,114,4,0,0,0,41, - 1,114,106,0,0,0,114,6,0,0,0,218,11,95,99,104, - 101,99,107,95,110,97,109,101,132,1,0,0,115,14,0,0, - 0,0,8,14,7,2,1,10,1,14,2,14,5,10,1,114, - 120,0,0,0,99,2,0,0,0,0,0,0,0,5,0,0, - 0,6,0,0,0,67,0,0,0,115,60,0,0,0,124,0, - 160,0,124,1,161,1,92,2,125,2,125,3,124,2,100,1, - 107,8,114,56,116,1,124,3,131,1,114,56,100,2,125,4, - 116,2,160,3,124,4,160,4,124,3,100,3,25,0,161,1, - 116,5,161,2,1,0,124,2,83,0,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,62,0,0,0,41,6,218, - 11,102,105,110,100,95,108,111,97,100,101,114,114,33,0,0, - 0,114,63,0,0,0,114,64,0,0,0,114,50,0,0,0, - 218,13,73,109,112,111,114,116,87,97,114,110,105,110,103,41, - 5,114,104,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,6,0,0,0,218,17,95,102,105,110,100,95,109,111, - 100,117,108,101,95,115,104,105,109,160,1,0,0,115,10,0, - 0,0,0,10,14,1,16,1,4,1,22,1,114,127,0,0, - 0,99,3,0,0,0,0,0,0,0,6,0,0,0,4,0, - 0,0,67,0,0,0,115,158,0,0,0,124,0,100,1,100, - 2,133,2,25,0,125,3,124,3,116,0,107,3,114,60,100, - 3,124,1,155,2,100,4,124,3,155,2,157,4,125,4,116, - 1,160,2,100,5,124,4,161,2,1,0,116,3,124,4,102, - 1,124,2,142,1,130,1,116,4,124,0,131,1,100,6,107, - 0,114,102,100,7,124,1,155,2,157,2,125,4,116,1,160, - 2,100,5,124,4,161,2,1,0,116,5,124,4,131,1,130, - 1,116,6,124,0,100,2,100,8,133,2,25,0,131,1,125, - 5,124,5,100,12,64,0,114,154,100,10,124,5,155,2,100, - 11,124,1,155,2,157,4,125,4,116,3,124,4,102,1,124, - 2,142,1,130,1,124,5,83,0,41,13,97,84,2,0,0, - 80,101,114,102,111,114,109,32,98,97,115,105,99,32,118,97, - 108,105,100,105,116,121,32,99,104,101,99,107,105,110,103,32, - 111,102,32,97,32,112,121,99,32,104,101,97,100,101,114,32, - 97,110,100,32,114,101,116,117,114,110,32,116,104,101,32,102, - 108,97,103,115,32,102,105,101,108,100,44,10,32,32,32,32, - 119,104,105,99,104,32,100,101,116,101,114,109,105,110,101,115, - 32,104,111,119,32,116,104,101,32,112,121,99,32,115,104,111, - 117,108,100,32,98,101,32,102,117,114,116,104,101,114,32,118, - 97,108,105,100,97,116,101,100,32,97,103,97,105,110,115,116, - 32,116,104,101,32,115,111,117,114,99,101,46,10,10,32,32, - 32,32,42,100,97,116,97,42,32,105,115,32,116,104,101,32, - 99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32, - 112,121,99,32,102,105,108,101,46,32,40,79,110,108,121,32, - 116,104,101,32,102,105,114,115,116,32,49,54,32,98,121,116, - 101,115,32,97,114,101,10,32,32,32,32,114,101,113,117,105, - 114,101,100,44,32,116,104,111,117,103,104,46,41,10,10,32, - 32,32,32,42,110,97,109,101,42,32,105,115,32,116,104,101, - 32,110,97,109,101,32,111,102,32,116,104,101,32,109,111,100, - 117,108,101,32,98,101,105,110,103,32,105,109,112,111,114,116, - 101,100,46,32,73,116,32,105,115,32,117,115,101,100,32,102, - 111,114,32,108,111,103,103,105,110,103,46,10,10,32,32,32, - 32,42,101,120,99,95,100,101,116,97,105,108,115,42,32,105, - 115,32,97,32,100,105,99,116,105,111,110,97,114,121,32,112, - 97,115,115,101,100,32,116,111,32,73,109,112,111,114,116,69, - 114,114,111,114,32,105,102,32,105,116,32,114,97,105,115,101, - 100,32,102,111,114,10,32,32,32,32,105,109,112,114,111,118, - 101,100,32,100,101,98,117,103,103,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,119, - 104,101,110,32,116,104,101,32,102,108,97,103,115,10,32,32, - 32,32,102,105,101,108,100,32,105,115,32,105,110,118,97,108, - 105,100,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,32,116,114,117,110,99,97,116,101,100,46,10,10, - 32,32,32,32,78,114,14,0,0,0,122,20,98,97,100,32, - 109,97,103,105,99,32,110,117,109,98,101,114,32,105,110,32, - 122,2,58,32,122,2,123,125,233,16,0,0,0,122,40,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,112,121,99,32,104,101,97, - 100,101,114,32,111,102,32,233,8,0,0,0,114,84,0,0, - 0,122,14,105,110,118,97,108,105,100,32,102,108,97,103,115, - 32,122,4,32,105,110,32,233,252,255,255,255,41,7,218,12, - 77,65,71,73,67,95,78,85,77,66,69,82,114,118,0,0, + 99,2,0,0,0,0,0,0,0,4,0,0,0,4,0,0, + 0,31,0,0,0,115,66,0,0,0,124,1,100,0,107,8, + 114,16,124,0,106,0,125,1,110,32,124,0,106,0,124,1, + 107,3,114,48,116,1,100,1,124,0,106,0,124,1,102,2, + 22,0,124,1,100,2,141,2,130,1,136,0,124,0,124,1, + 102,2,124,2,158,2,124,3,142,1,83,0,41,3,78,122, + 30,108,111,97,100,101,114,32,102,111,114,32,37,115,32,99, + 97,110,110,111,116,32,104,97,110,100,108,101,32,37,115,41, + 1,218,4,110,97,109,101,41,2,114,100,0,0,0,218,11, + 73,109,112,111,114,116,69,114,114,111,114,41,4,218,4,115, + 101,108,102,114,100,0,0,0,218,4,97,114,103,115,90,6, + 107,119,97,114,103,115,41,1,218,6,109,101,116,104,111,100, + 114,2,0,0,0,114,4,0,0,0,218,19,95,99,104,101, + 99,107,95,110,97,109,101,95,119,114,97,112,112,101,114,140, + 1,0,0,115,12,0,0,0,0,1,8,1,8,1,10,1, + 4,1,18,1,122,40,95,99,104,101,99,107,95,110,97,109, + 101,46,60,108,111,99,97,108,115,62,46,95,99,104,101,99, + 107,95,110,97,109,101,95,119,114,97,112,112,101,114,99,2, + 0,0,0,0,0,0,0,3,0,0,0,7,0,0,0,83, + 0,0,0,115,60,0,0,0,120,40,100,5,68,0,93,32, + 125,2,116,0,124,1,124,2,131,2,114,6,116,1,124,0, + 124,2,116,2,124,1,124,2,131,2,131,3,1,0,113,6, + 87,0,124,0,106,3,160,4,124,1,106,3,161,1,1,0, + 100,0,83,0,41,6,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,4,114,106,0,0,0,114,107,0,0,0, + 114,108,0,0,0,114,109,0,0,0,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,53,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,218,5,95,119,114,97,112, + 151,1,0,0,115,8,0,0,0,0,1,10,1,10,1,22, + 1,122,26,95,99,104,101,99,107,95,110,97,109,101,46,60, + 108,111,99,97,108,115,62,46,95,119,114,97,112,41,1,78, + 41,3,218,10,95,98,111,111,116,115,116,114,97,112,114,115, + 0,0,0,218,9,78,97,109,101,69,114,114,111,114,41,3, + 114,104,0,0,0,114,105,0,0,0,114,115,0,0,0,114, + 2,0,0,0,41,1,114,104,0,0,0,114,4,0,0,0, + 218,11,95,99,104,101,99,107,95,110,97,109,101,132,1,0, + 0,115,14,0,0,0,0,8,14,7,2,1,10,1,14,2, + 14,5,10,1,114,118,0,0,0,99,2,0,0,0,0,0, + 0,0,5,0,0,0,6,0,0,0,67,0,0,0,115,60, + 0,0,0,124,0,160,0,124,1,161,1,92,2,125,2,125, + 3,124,2,100,1,107,8,114,56,116,1,124,3,131,1,114, + 56,100,2,125,4,116,2,160,3,124,4,160,4,124,3,100, + 3,25,0,161,1,116,5,161,2,1,0,124,2,83,0,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,60,0, + 0,0,41,6,218,11,102,105,110,100,95,108,111,97,100,101, + 114,114,31,0,0,0,114,61,0,0,0,114,62,0,0,0, + 114,48,0,0,0,218,13,73,109,112,111,114,116,87,97,114, + 110,105,110,103,41,5,114,102,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,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,17,95,102,105, + 110,100,95,109,111,100,117,108,101,95,115,104,105,109,160,1, + 0,0,115,10,0,0,0,0,10,14,1,16,1,4,1,22, + 1,114,125,0,0,0,99,3,0,0,0,0,0,0,0,6, + 0,0,0,4,0,0,0,67,0,0,0,115,158,0,0,0, + 124,0,100,1,100,2,133,2,25,0,125,3,124,3,116,0, + 107,3,114,60,100,3,124,1,155,2,100,4,124,3,155,2, + 157,4,125,4,116,1,160,2,100,5,124,4,161,2,1,0, + 116,3,124,4,102,1,124,2,142,1,130,1,116,4,124,0, + 131,1,100,6,107,0,114,102,100,7,124,1,155,2,157,2, + 125,4,116,1,160,2,100,5,124,4,161,2,1,0,116,5, + 124,4,131,1,130,1,116,6,124,0,100,2,100,8,133,2, + 25,0,131,1,125,5,124,5,100,9,64,0,114,154,100,10, + 124,5,155,2,100,11,124,1,155,2,157,4,125,4,116,3, + 124,4,102,1,124,2,142,1,130,1,124,5,83,0,41,12, + 97,84,2,0,0,80,101,114,102,111,114,109,32,98,97,115, + 105,99,32,118,97,108,105,100,105,116,121,32,99,104,101,99, + 107,105,110,103,32,111,102,32,97,32,112,121,99,32,104,101, + 97,100,101,114,32,97,110,100,32,114,101,116,117,114,110,32, + 116,104,101,32,102,108,97,103,115,32,102,105,101,108,100,44, + 10,32,32,32,32,119,104,105,99,104,32,100,101,116,101,114, + 109,105,110,101,115,32,104,111,119,32,116,104,101,32,112,121, + 99,32,115,104,111,117,108,100,32,98,101,32,102,117,114,116, + 104,101,114,32,118,97,108,105,100,97,116,101,100,32,97,103, + 97,105,110,115,116,32,116,104,101,32,115,111,117,114,99,101, + 46,10,10,32,32,32,32,42,100,97,116,97,42,32,105,115, + 32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102, + 32,116,104,101,32,112,121,99,32,102,105,108,101,46,32,40, + 79,110,108,121,32,116,104,101,32,102,105,114,115,116,32,49, + 54,32,98,121,116,101,115,32,97,114,101,10,32,32,32,32, + 114,101,113,117,105,114,101,100,44,32,116,104,111,117,103,104, + 46,41,10,10,32,32,32,32,42,110,97,109,101,42,32,105, + 115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104, + 101,32,109,111,100,117,108,101,32,98,101,105,110,103,32,105, + 109,112,111,114,116,101,100,46,32,73,116,32,105,115,32,117, + 115,101,100,32,102,111,114,32,108,111,103,103,105,110,103,46, + 10,10,32,32,32,32,42,101,120,99,95,100,101,116,97,105, + 108,115,42,32,105,115,32,97,32,100,105,99,116,105,111,110, + 97,114,121,32,112,97,115,115,101,100,32,116,111,32,73,109, + 112,111,114,116,69,114,114,111,114,32,105,102,32,105,116,32, + 114,97,105,115,101,100,32,102,111,114,10,32,32,32,32,105, + 109,112,114,111,118,101,100,32,100,101,98,117,103,103,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,119,104,101,110,32,116,104,101,32,102,108,97, + 103,115,10,32,32,32,32,102,105,101,108,100,32,105,115,32, + 105,110,118,97,108,105,100,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,32,116,114,117,110,99,97,116, + 101,100,46,10,10,32,32,32,32,78,114,12,0,0,0,122, + 20,98,97,100,32,109,97,103,105,99,32,110,117,109,98,101, + 114,32,105,110,32,122,2,58,32,122,2,123,125,233,16,0, + 0,0,122,40,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,112,121, + 99,32,104,101,97,100,101,114,32,111,102,32,233,8,0,0, + 0,233,252,255,255,255,122,14,105,110,118,97,108,105,100,32, + 102,108,97,103,115,32,122,4,32,105,110,32,41,7,218,12, + 77,65,71,73,67,95,78,85,77,66,69,82,114,116,0,0, 0,218,16,95,118,101,114,98,111,115,101,95,109,101,115,115, - 97,103,101,114,103,0,0,0,114,33,0,0,0,218,8,69, - 79,70,69,114,114,111,114,114,21,0,0,0,41,6,114,56, - 0,0,0,114,102,0,0,0,218,11,101,120,99,95,100,101, - 116,97,105,108,115,90,5,109,97,103,105,99,114,79,0,0, - 0,114,71,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,13,95,99,108,97,115,115,105,102,121, + 97,103,101,114,101,0,0,0,114,31,0,0,0,218,8,69, + 79,70,69,114,114,111,114,114,19,0,0,0,41,6,114,54, + 0,0,0,114,100,0,0,0,218,11,101,120,99,95,100,101, + 116,97,105,108,115,90,5,109,97,103,105,99,114,77,0,0, + 0,114,69,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,13,95,99,108,97,115,115,105,102,121, 95,112,121,99,177,1,0,0,115,28,0,0,0,0,16,12, 1,8,1,16,1,12,1,12,1,12,1,10,1,12,1,8, - 1,16,2,8,1,16,1,12,1,114,135,0,0,0,99,5, + 1,16,2,8,1,16,1,12,1,114,133,0,0,0,99,5, 0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,67, 0,0,0,115,112,0,0,0,116,0,124,0,100,1,100,2, 133,2,25,0,131,1,124,1,100,3,64,0,107,3,114,58, @@ -688,19 +687,19 @@ const unsigned char _Py_M__importlib_external[] = { 32,73,109,112,111,114,116,69,114,114,111,114,32,105,115,32, 114,97,105,115,101,100,32,105,102,32,116,104,101,32,98,121, 116,101,99,111,100,101,32,105,115,32,115,116,97,108,101,46, - 10,10,32,32,32,32,114,129,0,0,0,233,12,0,0,0, + 10,10,32,32,32,32,114,127,0,0,0,233,12,0,0,0, 108,3,0,0,0,255,127,255,127,3,0,122,22,98,121,116, 101,99,111,100,101,32,105,115,32,115,116,97,108,101,32,102, - 111,114,32,122,2,123,125,78,114,128,0,0,0,41,4,114, - 21,0,0,0,114,118,0,0,0,114,132,0,0,0,114,103, - 0,0,0,41,6,114,56,0,0,0,218,12,115,111,117,114, + 111,114,32,122,2,123,125,78,114,126,0,0,0,41,4,114, + 19,0,0,0,114,116,0,0,0,114,130,0,0,0,114,101, + 0,0,0,41,6,114,54,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,102,0,0,0,114,134,0,0,0,114, - 79,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 95,115,105,122,101,114,100,0,0,0,114,132,0,0,0,114, + 77,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, 0,0,0,218,23,95,118,97,108,105,100,97,116,101,95,116, 105,109,101,115,116,97,109,112,95,112,121,99,210,1,0,0, 115,14,0,0,0,0,19,24,1,10,1,12,1,12,1,8, - 1,24,1,114,139,0,0,0,99,4,0,0,0,0,0,0, + 1,24,1,114,137,0,0,0,99,4,0,0,0,0,0,0, 0,4,0,0,0,3,0,0,0,67,0,0,0,115,38,0, 0,0,124,0,100,1,100,2,133,2,25,0,124,1,107,3, 114,34,116,0,100,3,124,2,155,2,157,2,102,1,124,3, @@ -736,16 +735,16 @@ const unsigned char _Py_M__importlib_external[] = { 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, 101,100,32,105,102,32,116,104,101,32,98,121,116,101,99,111, 100,101,32,105,115,32,115,116,97,108,101,46,10,10,32,32, - 32,32,114,129,0,0,0,114,128,0,0,0,122,46,104,97, + 32,32,114,127,0,0,0,114,126,0,0,0,122,46,104,97, 115,104,32,105,110,32,98,121,116,101,99,111,100,101,32,100, 111,101,115,110,39,116,32,109,97,116,99,104,32,104,97,115, 104,32,111,102,32,115,111,117,114,99,101,32,78,41,1,114, - 103,0,0,0,41,4,114,56,0,0,0,218,11,115,111,117, - 114,99,101,95,104,97,115,104,114,102,0,0,0,114,134,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 101,0,0,0,41,4,114,54,0,0,0,218,11,115,111,117, + 114,99,101,95,104,97,115,104,114,100,0,0,0,114,132,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,18,95,118,97,108,105,100,97,116,101,95,104,97,115, 104,95,112,121,99,238,1,0,0,115,8,0,0,0,0,17, - 16,1,2,1,10,1,114,141,0,0,0,99,4,0,0,0, + 16,1,2,1,10,1,114,139,0,0,0,99,4,0,0,0, 0,0,0,0,5,0,0,0,5,0,0,0,67,0,0,0, 115,80,0,0,0,116,0,160,1,124,0,161,1,125,4,116, 2,124,4,116,3,131,2,114,56,116,4,160,5,100,1,124, @@ -758,18 +757,18 @@ const unsigned char _Py_M__importlib_external[] = { 100,101,32,111,98,106,101,99,116,32,102,114,111,109,32,123, 33,114,125,78,122,23,78,111,110,45,99,111,100,101,32,111, 98,106,101,99,116,32,105,110,32,123,33,114,125,41,2,114, - 102,0,0,0,114,37,0,0,0,41,10,218,7,109,97,114, + 100,0,0,0,114,35,0,0,0,41,10,218,7,109,97,114, 115,104,97,108,90,5,108,111,97,100,115,218,10,105,115,105, 110,115,116,97,110,99,101,218,10,95,99,111,100,101,95,116, - 121,112,101,114,118,0,0,0,114,132,0,0,0,218,4,95, + 121,112,101,114,116,0,0,0,114,130,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,103,0,0,0,114,50,0,0,0,41, - 5,114,56,0,0,0,114,102,0,0,0,114,93,0,0,0, - 114,94,0,0,0,218,4,99,111,100,101,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,218,17,95,99,111,109, + 101,110,97,109,101,114,101,0,0,0,114,48,0,0,0,41, + 5,114,54,0,0,0,114,100,0,0,0,114,91,0,0,0, + 114,92,0,0,0,218,4,99,111,100,101,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,218,17,95,99,111,109, 112,105,108,101,95,98,121,116,101,99,111,100,101,6,2,0, 0,115,16,0,0,0,0,2,10,1,10,1,12,1,8,1, - 12,1,4,2,10,1,114,147,0,0,0,114,62,0,0,0, + 12,1,4,2,10,1,114,145,0,0,0,114,60,0,0,0, 99,3,0,0,0,0,0,0,0,4,0,0,0,5,0,0, 0,67,0,0,0,115,70,0,0,0,116,0,116,1,131,1, 125,3,124,3,160,2,116,3,100,1,131,1,161,1,1,0, @@ -779,15 +778,15 @@ const unsigned char _Py_M__importlib_external[] = { 41,2,122,43,80,114,111,100,117,99,101,32,116,104,101,32, 100,97,116,97,32,102,111,114,32,97,32,116,105,109,101,115, 116,97,109,112,45,98,97,115,101,100,32,112,121,99,46,114, - 62,0,0,0,41,6,218,9,98,121,116,101,97,114,114,97, - 121,114,131,0,0,0,218,6,101,120,116,101,110,100,114,19, - 0,0,0,114,142,0,0,0,218,5,100,117,109,112,115,41, - 4,114,146,0,0,0,218,5,109,116,105,109,101,114,138,0, - 0,0,114,56,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,22,95,99,111,100,101,95,116,111, + 60,0,0,0,41,6,218,9,98,121,116,101,97,114,114,97, + 121,114,129,0,0,0,218,6,101,120,116,101,110,100,114,17, + 0,0,0,114,140,0,0,0,218,5,100,117,109,112,115,41, + 4,114,144,0,0,0,218,5,109,116,105,109,101,114,136,0, + 0,0,114,54,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,218,22,95,99,111,100,101,95,116,111, 95,116,105,109,101,115,116,97,109,112,95,112,121,99,19,2, 0,0,115,12,0,0,0,0,2,8,1,14,1,14,1,14, - 1,16,1,114,152,0,0,0,84,99,3,0,0,0,0,0, + 1,16,1,114,150,0,0,0,84,99,3,0,0,0,0,0, 0,0,5,0,0,0,5,0,0,0,67,0,0,0,115,80, 0,0,0,116,0,116,1,131,1,125,3,100,1,124,2,100, 1,62,0,66,0,125,4,124,3,160,2,116,3,124,4,131, @@ -796,17 +795,17 @@ const unsigned char _Py_M__importlib_external[] = { 3,160,2,116,6,160,7,124,0,161,1,161,1,1,0,124, 3,83,0,41,3,122,38,80,114,111,100,117,99,101,32,116, 104,101,32,100,97,116,97,32,102,111,114,32,97,32,104,97, - 115,104,45,98,97,115,101,100,32,112,121,99,46,114,31,0, - 0,0,114,129,0,0,0,41,8,114,148,0,0,0,114,131, - 0,0,0,114,149,0,0,0,114,19,0,0,0,114,33,0, + 115,104,45,98,97,115,101,100,32,112,121,99,46,114,29,0, + 0,0,114,127,0,0,0,41,8,114,146,0,0,0,114,129, + 0,0,0,114,147,0,0,0,114,17,0,0,0,114,31,0, 0,0,218,14,65,115,115,101,114,116,105,111,110,69,114,114, - 111,114,114,142,0,0,0,114,150,0,0,0,41,5,114,146, - 0,0,0,114,140,0,0,0,90,7,99,104,101,99,107,101, - 100,114,56,0,0,0,114,71,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,218,17,95,99,111,100, + 111,114,114,140,0,0,0,114,148,0,0,0,41,5,114,144, + 0,0,0,114,138,0,0,0,90,7,99,104,101,99,107,101, + 100,114,54,0,0,0,114,69,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,218,17,95,99,111,100, 101,95,116,111,95,104,97,115,104,95,112,121,99,29,2,0, 0,115,14,0,0,0,0,2,8,1,12,1,14,1,16,1, - 10,1,16,1,114,154,0,0,0,99,1,0,0,0,0,0, + 10,1,16,1,114,152,0,0,0,99,1,0,0,0,0,0, 0,0,5,0,0,0,6,0,0,0,67,0,0,0,115,62, 0,0,0,100,1,100,2,108,0,125,1,116,1,160,2,124, 0,161,1,106,3,125,2,124,1,160,4,124,2,161,1,125, @@ -819,21 +818,21 @@ const unsigned char _Py_M__importlib_external[] = { 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,62, + 100,101,99,111,100,105,110,103,46,10,32,32,32,32,114,60, 0,0,0,78,84,41,7,218,8,116,111,107,101,110,105,122, - 101,114,52,0,0,0,90,7,66,121,116,101,115,73,79,90, + 101,114,50,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,155,0, + 12,115,111,117,114,99,101,95,98,121,116,101,115,114,153,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,6, + 111,100,101,114,114,2,0,0,0,114,2,0,0,0,114,4, 0,0,0,218,13,100,101,99,111,100,101,95,115,111,117,114, 99,101,40,2,0,0,115,10,0,0,0,0,5,8,1,12, - 1,10,1,12,1,114,159,0,0,0,41,2,114,124,0,0, + 1,10,1,12,1,114,157,0,0,0,41,2,114,122,0,0, 0,218,26,115,117,98,109,111,100,117,108,101,95,115,101,97, 114,99,104,95,108,111,99,97,116,105,111,110,115,99,2,0, 0,0,2,0,0,0,9,0,0,0,19,0,0,0,67,0, @@ -877,28 +876,28 @@ const unsigned char _Py_M__importlib_external[] = { 40,41,32,97,114,103,46,10,10,32,32,32,32,78,122,9, 60,117,110,107,110,111,119,110,62,218,12,103,101,116,95,102, 105,108,101,110,97,109,101,41,1,218,6,111,114,105,103,105, - 110,84,218,10,105,115,95,112,97,99,107,97,103,101,114,62, - 0,0,0,41,17,114,112,0,0,0,114,161,0,0,0,114, - 103,0,0,0,114,3,0,0,0,114,67,0,0,0,114,118, + 110,84,218,10,105,115,95,112,97,99,107,97,103,101,114,60, + 0,0,0,41,17,114,110,0,0,0,114,159,0,0,0,114, + 101,0,0,0,114,1,0,0,0,114,65,0,0,0,114,116, 0,0,0,218,10,77,111,100,117,108,101,83,112,101,99,90, 13,95,115,101,116,95,102,105,108,101,97,116,116,114,218,27, 95,103,101,116,95,115,117,112,112,111,114,116,101,100,95,102, - 105,108,101,95,108,111,97,100,101,114,115,114,96,0,0,0, - 114,97,0,0,0,114,124,0,0,0,218,9,95,80,79,80, - 85,76,65,84,69,114,163,0,0,0,114,160,0,0,0,114, - 40,0,0,0,218,6,97,112,112,101,110,100,41,9,114,102, - 0,0,0,90,8,108,111,99,97,116,105,111,110,114,124,0, - 0,0,114,160,0,0,0,218,4,115,112,101,99,218,12,108, + 105,108,101,95,108,111,97,100,101,114,115,114,94,0,0,0, + 114,95,0,0,0,114,122,0,0,0,218,9,95,80,79,80, + 85,76,65,84,69,114,161,0,0,0,114,158,0,0,0,114, + 38,0,0,0,218,6,97,112,112,101,110,100,41,9,114,100, + 0,0,0,90,8,108,111,99,97,116,105,111,110,114,122,0, + 0,0,114,158,0,0,0,218,4,115,112,101,99,218,12,108, 111,97,100,101,114,95,99,108,97,115,115,218,8,115,117,102, - 102,105,120,101,115,114,163,0,0,0,90,7,100,105,114,110, - 97,109,101,114,4,0,0,0,114,4,0,0,0,114,6,0, + 102,105,120,101,115,114,161,0,0,0,90,7,100,105,114,110, + 97,109,101,114,2,0,0,0,114,2,0,0,0,114,4,0, 0,0,218,23,115,112,101,99,95,102,114,111,109,95,102,105, 108,101,95,108,111,99,97,116,105,111,110,57,2,0,0,115, 62,0,0,0,0,12,8,4,4,1,10,2,2,1,14,1, 14,1,8,2,10,8,16,1,6,3,8,1,16,1,14,1, 10,1,6,1,6,2,4,3,8,2,10,1,2,1,14,1, 14,1,6,2,4,1,8,2,6,1,12,1,6,1,12,1, - 12,2,114,171,0,0,0,99,0,0,0,0,0,0,0,0, + 12,2,114,169,0,0,0,99,0,0,0,0,0,0,0,0, 0,0,0,0,4,0,0,0,64,0,0,0,115,80,0,0, 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,90, 4,100,3,90,5,100,4,90,6,101,7,100,5,100,6,132, @@ -926,10 +925,10 @@ const unsigned char _Py_M__importlib_external[] = { 0,88,0,100,0,83,0,41,1,78,41,5,218,7,95,119, 105,110,114,101,103,90,7,79,112,101,110,75,101,121,90,17, 72,75,69,89,95,67,85,82,82,69,78,84,95,85,83,69, - 82,114,42,0,0,0,90,18,72,75,69,89,95,76,79,67, + 82,114,40,0,0,0,90,18,72,75,69,89,95,76,79,67, 65,76,95,77,65,67,72,73,78,69,41,2,218,3,99,108, - 115,114,5,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,14,95,111,112,101,110,95,114,101,103, + 115,114,3,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,14,95,111,112,101,110,95,114,101,103, 105,115,116,114,121,137,2,0,0,115,8,0,0,0,0,2, 2,1,14,1,14,1,122,36,87,105,110,100,111,119,115,82, 101,103,105,115,116,114,121,70,105,110,100,101,114,46,95,111, @@ -943,18 +942,18 @@ const unsigned char _Py_M__importlib_external[] = { 87,0,100,0,81,0,82,0,88,0,87,0,110,20,4,0, 116,9,107,10,114,106,1,0,1,0,1,0,100,0,83,0, 88,0,124,5,83,0,41,5,78,122,5,37,100,46,37,100, - 114,59,0,0,0,41,2,114,123,0,0,0,90,11,115,121, - 115,95,118,101,114,115,105,111,110,114,32,0,0,0,41,10, + 114,57,0,0,0,41,2,114,121,0,0,0,90,11,115,121, + 115,95,118,101,114,115,105,111,110,114,30,0,0,0,41,10, 218,11,68,69,66,85,71,95,66,85,73,76,68,218,18,82, 69,71,73,83,84,82,89,95,75,69,89,95,68,69,66,85, 71,218,12,82,69,71,73,83,84,82,89,95,75,69,89,114, - 50,0,0,0,114,8,0,0,0,218,12,118,101,114,115,105, - 111,110,95,105,110,102,111,114,175,0,0,0,114,173,0,0, - 0,90,10,81,117,101,114,121,86,97,108,117,101,114,42,0, - 0,0,41,6,114,174,0,0,0,114,123,0,0,0,90,12, - 114,101,103,105,115,116,114,121,95,107,101,121,114,5,0,0, + 48,0,0,0,114,6,0,0,0,218,12,118,101,114,115,105, + 111,110,95,105,110,102,111,114,173,0,0,0,114,171,0,0, + 0,90,10,81,117,101,114,121,86,97,108,117,101,114,40,0, + 0,0,41,6,114,172,0,0,0,114,121,0,0,0,90,12, + 114,101,103,105,115,116,114,121,95,107,101,121,114,3,0,0, 0,90,4,104,107,101,121,218,8,102,105,108,101,112,97,116, - 104,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, + 104,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, 218,16,95,115,101,97,114,99,104,95,114,101,103,105,115,116, 114,121,144,2,0,0,115,22,0,0,0,0,2,6,1,8, 2,6,1,6,1,22,1,2,1,12,1,26,1,14,1,6, @@ -970,14 +969,14 @@ const unsigned char _Py_M__importlib_external[] = { 116,5,124,6,131,1,161,1,114,64,116,6,106,7,124,1, 124,5,124,1,124,4,131,2,124,4,100,1,141,3,125,7, 124,7,83,0,113,64,87,0,100,0,83,0,41,2,78,41, - 1,114,162,0,0,0,41,8,114,181,0,0,0,114,41,0, - 0,0,114,42,0,0,0,114,165,0,0,0,114,96,0,0, - 0,114,97,0,0,0,114,118,0,0,0,218,16,115,112,101, + 1,114,160,0,0,0,41,8,114,179,0,0,0,114,39,0, + 0,0,114,40,0,0,0,114,163,0,0,0,114,94,0,0, + 0,114,95,0,0,0,114,116,0,0,0,218,16,115,112,101, 99,95,102,114,111,109,95,108,111,97,100,101,114,41,8,114, - 174,0,0,0,114,123,0,0,0,114,37,0,0,0,218,6, - 116,97,114,103,101,116,114,180,0,0,0,114,124,0,0,0, - 114,170,0,0,0,114,168,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,218,9,102,105,110,100,95, + 172,0,0,0,114,121,0,0,0,114,35,0,0,0,218,6, + 116,97,114,103,101,116,114,178,0,0,0,114,122,0,0,0, + 114,168,0,0,0,114,166,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,218,9,102,105,110,100,95, 115,112,101,99,159,2,0,0,115,26,0,0,0,0,2,10, 1,8,1,4,1,2,1,12,1,14,1,6,1,16,1,14, 1,6,1,8,1,8,1,122,31,87,105,110,100,111,119,115, @@ -993,22 +992,22 @@ const unsigned char _Py_M__importlib_external[] = { 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,124,0,0, - 0,41,4,114,174,0,0,0,114,123,0,0,0,114,37,0, - 0,0,114,168,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,11,102,105,110,100,95,109,111,100, + 32,32,32,32,78,41,2,114,182,0,0,0,114,122,0,0, + 0,41,4,114,172,0,0,0,114,121,0,0,0,114,35,0, + 0,0,114,166,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,218,11,102,105,110,100,95,109,111,100, 117,108,101,175,2,0,0,115,8,0,0,0,0,7,12,1, 8,1,6,2,122,33,87,105,110,100,111,119,115,82,101,103, 105,115,116,114,121,70,105,110,100,101,114,46,102,105,110,100, 95,109,111,100,117,108,101,41,2,78,78,41,1,78,41,12, - 114,109,0,0,0,114,108,0,0,0,114,110,0,0,0,114, - 111,0,0,0,114,178,0,0,0,114,177,0,0,0,114,176, + 114,107,0,0,0,114,106,0,0,0,114,108,0,0,0,114, + 109,0,0,0,114,176,0,0,0,114,175,0,0,0,114,174, 0,0,0,218,11,99,108,97,115,115,109,101,116,104,111,100, - 114,175,0,0,0,114,181,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,6,0,0,0,114,172,0,0,0,125,2,0, + 114,173,0,0,0,114,179,0,0,0,114,182,0,0,0,114, + 183,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,170,0,0,0,125,2,0, 0,115,18,0,0,0,12,5,4,3,4,2,4,2,12,7, - 12,15,2,1,12,15,2,1,114,172,0,0,0,99,0,0, + 12,15,2,1,12,15,2,1,114,170,0,0,0,99,0,0, 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, 0,0,115,48,0,0,0,101,0,90,1,100,0,90,2,100, 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, @@ -1034,14 +1033,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,31,0,0,0,114,61,0, - 0,0,114,62,0,0,0,114,59,0,0,0,218,8,95,95, - 105,110,105,116,95,95,41,4,114,40,0,0,0,114,161,0, - 0,0,114,36,0,0,0,114,34,0,0,0,41,5,114,104, - 0,0,0,114,123,0,0,0,114,98,0,0,0,90,13,102, + 116,95,95,46,112,121,39,46,114,29,0,0,0,114,59,0, + 0,0,114,60,0,0,0,114,57,0,0,0,218,8,95,95, + 105,110,105,116,95,95,41,4,114,38,0,0,0,114,159,0, + 0,0,114,34,0,0,0,114,32,0,0,0,41,5,114,102, + 0,0,0,114,121,0,0,0,114,96,0,0,0,90,13,102, 105,108,101,110,97,109,101,95,98,97,115,101,90,9,116,97, - 105,108,95,110,97,109,101,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,163,0,0,0,194,2,0,0,115, + 105,108,95,110,97,109,101,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,161,0,0,0,194,2,0,0,115, 8,0,0,0,0,3,18,1,16,1,14,1,122,24,95,76, 111,97,100,101,114,66,97,115,105,99,115,46,105,115,95,112, 97,99,107,97,103,101,99,2,0,0,0,0,0,0,0,2, @@ -1049,8 +1048,8 @@ const unsigned char _Py_M__importlib_external[] = { 100,1,83,0,41,2,122,42,85,115,101,32,100,101,102,97, 117,108,116,32,115,101,109,97,110,116,105,99,115,32,102,111, 114,32,109,111,100,117,108,101,32,99,114,101,97,116,105,111, - 110,46,78,114,4,0,0,0,41,2,114,104,0,0,0,114, - 168,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 110,46,78,114,2,0,0,0,41,2,114,102,0,0,0,114, + 166,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, 0,0,0,218,13,99,114,101,97,116,101,95,109,111,100,117, 108,101,202,2,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, @@ -1065,12 +1064,12 @@ const unsigned char _Py_M__importlib_external[] = { 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,109,0,0,0,114,103,0,0,0,114,50, - 0,0,0,114,118,0,0,0,218,25,95,99,97,108,108,95, + 99,111,100,101,114,107,0,0,0,114,101,0,0,0,114,48, + 0,0,0,114,116,0,0,0,218,25,95,99,97,108,108,95, 119,105,116,104,95,102,114,97,109,101,115,95,114,101,109,111, - 118,101,100,218,4,101,120,101,99,114,115,0,0,0,41,3, - 114,104,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,6,0,0, + 118,101,100,218,4,101,120,101,99,114,113,0,0,0,41,3, + 114,102,0,0,0,218,6,109,111,100,117,108,101,114,144,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,11,101,120,101,99,95,109,111,100,117,108,101,205,2, 0,0,115,10,0,0,0,0,2,12,1,8,1,6,1,10, 1,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, @@ -1079,25 +1078,25 @@ const unsigned char _Py_M__importlib_external[] = { 0,115,12,0,0,0,116,0,160,1,124,0,124,1,161,2, 83,0,41,1,122,26,84,104,105,115,32,109,111,100,117,108, 101,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 41,2,114,118,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,104,0,0, - 0,114,123,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,11,108,111,97,100,95,109,111,100,117, + 41,2,114,116,0,0,0,218,17,95,108,111,97,100,95,109, + 111,100,117,108,101,95,115,104,105,109,41,2,114,102,0,0, + 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,11,108,111,97,100,95,109,111,100,117, 108,101,213,2,0,0,115,2,0,0,0,0,2,122,25,95, 76,111,97,100,101,114,66,97,115,105,99,115,46,108,111,97, - 100,95,109,111,100,117,108,101,78,41,8,114,109,0,0,0, - 114,108,0,0,0,114,110,0,0,0,114,111,0,0,0,114, - 163,0,0,0,114,189,0,0,0,114,194,0,0,0,114,196, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,114,187,0,0,0,189,2,0,0, - 115,8,0,0,0,12,5,8,8,8,3,8,8,114,187,0, + 100,95,109,111,100,117,108,101,78,41,8,114,107,0,0,0, + 114,106,0,0,0,114,108,0,0,0,114,109,0,0,0,114, + 161,0,0,0,114,187,0,0,0,114,192,0,0,0,114,194, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,114,185,0,0,0,189,2,0,0, + 115,8,0,0,0,12,5,8,8,8,3,8,8,114,185,0, 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,3, 0,0,0,64,0,0,0,115,74,0,0,0,101,0,90,1, 100,0,90,2,100,1,100,2,132,0,90,3,100,3,100,4, 132,0,90,4,100,5,100,6,132,0,90,5,100,7,100,8, - 132,0,90,6,100,9,100,10,132,0,90,7,100,18,100,12, + 132,0,90,6,100,9,100,10,132,0,90,7,100,11,100,12, 156,1,100,13,100,14,132,2,90,8,100,15,100,16,132,0, - 90,9,100,17,83,0,41,19,218,12,83,111,117,114,99,101, + 90,9,100,17,83,0,41,18,218,12,83,111,117,114,99,101, 76,111,97,100,101,114,99,2,0,0,0,0,0,0,0,2, 0,0,0,1,0,0,0,67,0,0,0,115,8,0,0,0, 116,0,130,1,100,1,83,0,41,2,122,178,79,112,116,105, @@ -1112,8 +1111,8 @@ const unsigned char _Py_M__importlib_external[] = { 114,114,111,114,32,119,104,101,110,32,116,104,101,32,112,97, 116,104,32,99,97,110,110,111,116,32,98,101,32,104,97,110, 100,108,101,100,46,10,32,32,32,32,32,32,32,32,78,41, - 1,114,42,0,0,0,41,2,114,104,0,0,0,114,37,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 1,114,40,0,0,0,41,2,114,102,0,0,0,114,35,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,10,112,97,116,104,95,109,116,105,109,101,220,2,0, 0,115,2,0,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, @@ -1146,9 +1145,9 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,82,97,105,115,101,115,32,79,83,69,114,114,111,114, 32,119,104,101,110,32,116,104,101,32,112,97,116,104,32,99, 97,110,110,111,116,32,98,101,32,104,97,110,100,108,101,100, - 46,10,32,32,32,32,32,32,32,32,114,151,0,0,0,41, - 1,114,198,0,0,0,41,2,114,104,0,0,0,114,37,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 46,10,32,32,32,32,32,32,32,32,114,149,0,0,0,41, + 1,114,196,0,0,0,41,2,114,102,0,0,0,114,35,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,10,112,97,116,104,95,115,116,97,116,115,228,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, @@ -1169,10 +1168,10 @@ const unsigned char _Py_M__importlib_external[] = { 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,104,0, - 0,0,114,94,0,0,0,90,10,99,97,99,104,101,95,112, - 97,116,104,114,56,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,218,15,95,99,97,99,104,101,95, + 1,218,8,115,101,116,95,100,97,116,97,41,4,114,102,0, + 0,0,114,92,0,0,0,90,10,99,97,99,104,101,95,112, + 97,116,104,114,54,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,15,95,99,97,99,104,101,95, 98,121,116,101,99,111,100,101,241,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, @@ -1187,10 +1186,10 @@ const unsigned char _Py_M__importlib_external[] = { 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,104,0,0,0,114,37,0,0,0,114,56,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, - 200,0,0,0,251,2,0,0,115,0,0,0,0,122,21,83, + 10,32,32,32,32,32,32,32,32,78,114,2,0,0,0,41, + 3,114,102,0,0,0,114,35,0,0,0,114,54,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 198,0,0,0,251,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,82,0,0,0,124,0, @@ -1205,16 +1204,16 @@ const unsigned char _Py_M__importlib_external[] = { 95,115,111,117,114,99,101,46,122,39,115,111,117,114,99,101, 32,110,111,116,32,97,118,97,105,108,97,98,108,101,32,116, 104,114,111,117,103,104,32,103,101,116,95,100,97,116,97,40, - 41,41,1,114,102,0,0,0,78,41,5,114,161,0,0,0, - 218,8,103,101,116,95,100,97,116,97,114,42,0,0,0,114, - 103,0,0,0,114,159,0,0,0,41,5,114,104,0,0,0, - 114,123,0,0,0,114,37,0,0,0,114,157,0,0,0,218, - 3,101,120,99,114,4,0,0,0,114,4,0,0,0,114,6, + 41,41,1,114,100,0,0,0,78,41,5,114,159,0,0,0, + 218,8,103,101,116,95,100,97,116,97,114,40,0,0,0,114, + 101,0,0,0,114,157,0,0,0,41,5,114,102,0,0,0, + 114,121,0,0,0,114,35,0,0,0,114,155,0,0,0,218, + 3,101,120,99,114,2,0,0,0,114,2,0,0,0,114,4, 0,0,0,218,10,103,101,116,95,115,111,117,114,99,101,2, 3,0,0,115,14,0,0,0,0,2,10,1,2,1,14,1, 16,1,4,1,28,1,122,23,83,111,117,114,99,101,76,111, 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,114, - 31,0,0,0,41,1,218,9,95,111,112,116,105,109,105,122, + 89,0,0,0,41,1,218,9,95,111,112,116,105,109,105,122, 101,99,3,0,0,0,1,0,0,0,4,0,0,0,8,0, 0,0,67,0,0,0,115,22,0,0,0,116,0,106,1,116, 2,124,1,124,2,100,1,100,2,124,3,100,3,141,6,83, @@ -1226,12 +1225,12 @@ const unsigned char _Py_M__importlib_external[] = { 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,84,41,2,218, - 12,100,111,110,116,95,105,110,104,101,114,105,116,114,72,0, - 0,0,41,3,114,118,0,0,0,114,191,0,0,0,218,7, - 99,111,109,112,105,108,101,41,4,114,104,0,0,0,114,56, - 0,0,0,114,37,0,0,0,114,205,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,218,14,115,111, + 32,32,32,32,32,32,32,114,190,0,0,0,84,41,2,218, + 12,100,111,110,116,95,105,110,104,101,114,105,116,114,70,0, + 0,0,41,3,114,116,0,0,0,114,189,0,0,0,218,7, + 99,111,109,112,105,108,101,41,4,114,102,0,0,0,114,54, + 0,0,0,114,35,0,0,0,114,203,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,218,14,115,111, 117,114,99,101,95,116,111,95,99,111,100,101,12,3,0,0, 115,4,0,0,0,0,5,12,1,122,27,83,111,117,114,99, 101,76,111,97,100,101,114,46,115,111,117,114,99,101,95,116, @@ -1284,34 +1283,34 @@ const unsigned char _Py_M__importlib_external[] = { 100,101,44,32,115,101,116,95,100,97,116,97,32,109,117,115, 116,32,97,108,115,111,32,98,101,32,105,109,112,108,101,109, 101,110,116,101,100,46,10,10,32,32,32,32,32,32,32,32, - 78,70,84,114,151,0,0,0,41,2,114,102,0,0,0,114, - 37,0,0,0,114,128,0,0,0,114,31,0,0,0,114,62, - 0,0,0,114,59,0,0,0,90,5,110,101,118,101,114,90, + 78,70,84,114,149,0,0,0,41,2,114,100,0,0,0,114, + 35,0,0,0,114,126,0,0,0,114,29,0,0,0,114,60, + 0,0,0,114,57,0,0,0,90,5,110,101,118,101,114,90, 6,97,108,119,97,121,115,218,4,115,105,122,101,122,13,123, - 125,32,109,97,116,99,104,101,115,32,123,125,41,3,114,102, - 0,0,0,114,93,0,0,0,114,94,0,0,0,122,19,99, + 125,32,109,97,116,99,104,101,115,32,123,125,41,3,114,100, + 0,0,0,114,91,0,0,0,114,92,0,0,0,122,19,99, 111,100,101,32,111,98,106,101,99,116,32,102,114,111,109,32, 123,125,122,10,119,114,111,116,101,32,123,33,114,125,41,27, - 114,161,0,0,0,114,83,0,0,0,114,70,0,0,0,114, - 199,0,0,0,114,42,0,0,0,114,16,0,0,0,114,202, - 0,0,0,114,135,0,0,0,218,10,109,101,109,111,114,121, - 118,105,101,119,114,145,0,0,0,90,21,99,104,101,99,107, + 114,159,0,0,0,114,81,0,0,0,114,68,0,0,0,114, + 197,0,0,0,114,40,0,0,0,114,14,0,0,0,114,200, + 0,0,0,114,133,0,0,0,218,10,109,101,109,111,114,121, + 118,105,101,119,114,143,0,0,0,90,21,99,104,101,99,107, 95,104,97,115,104,95,98,97,115,101,100,95,112,121,99,115, - 114,140,0,0,0,218,17,95,82,65,87,95,77,65,71,73, - 67,95,78,85,77,66,69,82,114,141,0,0,0,114,139,0, - 0,0,114,103,0,0,0,114,133,0,0,0,114,118,0,0, - 0,114,132,0,0,0,114,147,0,0,0,114,208,0,0,0, - 114,8,0,0,0,218,19,100,111,110,116,95,119,114,105,116, - 101,95,98,121,116,101,99,111,100,101,114,154,0,0,0,114, - 152,0,0,0,114,33,0,0,0,114,201,0,0,0,41,15, - 114,104,0,0,0,114,123,0,0,0,114,94,0,0,0,114, - 137,0,0,0,114,157,0,0,0,114,140,0,0,0,90,10, + 114,138,0,0,0,218,17,95,82,65,87,95,77,65,71,73, + 67,95,78,85,77,66,69,82,114,139,0,0,0,114,137,0, + 0,0,114,101,0,0,0,114,131,0,0,0,114,116,0,0, + 0,114,130,0,0,0,114,145,0,0,0,114,206,0,0,0, + 114,6,0,0,0,218,19,100,111,110,116,95,119,114,105,116, + 101,95,98,121,116,101,99,111,100,101,114,152,0,0,0,114, + 150,0,0,0,114,31,0,0,0,114,199,0,0,0,41,15, + 114,102,0,0,0,114,121,0,0,0,114,92,0,0,0,114, + 135,0,0,0,114,155,0,0,0,114,138,0,0,0,90,10, 104,97,115,104,95,98,97,115,101,100,90,12,99,104,101,99, - 107,95,115,111,117,114,99,101,114,93,0,0,0,218,2,115, - 116,114,56,0,0,0,114,134,0,0,0,114,71,0,0,0, + 107,95,115,111,117,114,99,101,114,91,0,0,0,218,2,115, + 116,114,54,0,0,0,114,132,0,0,0,114,69,0,0,0, 90,10,98,121,116,101,115,95,100,97,116,97,90,11,99,111, - 100,101,95,111,98,106,101,99,116,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,114,190,0,0,0,20,3,0, + 100,101,95,111,98,106,101,99,116,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,188,0,0,0,20,3,0, 0,115,134,0,0,0,0,7,10,1,4,1,4,1,4,1, 4,1,4,1,2,1,12,1,14,1,12,2,2,1,14,1, 14,1,8,2,12,1,2,1,14,1,14,1,6,3,2,1, @@ -1322,1238 +1321,1233 @@ const unsigned char _Py_M__importlib_external[] = { 12,1,18,1,10,1,6,1,10,1,10,1,14,2,6,1, 10,1,2,1,14,1,16,1,16,1,6,1,122,21,83,111, 117,114,99,101,76,111,97,100,101,114,46,103,101,116,95,99, - 111,100,101,78,114,91,0,0,0,41,10,114,109,0,0,0, - 114,108,0,0,0,114,110,0,0,0,114,198,0,0,0,114, - 199,0,0,0,114,201,0,0,0,114,200,0,0,0,114,204, - 0,0,0,114,208,0,0,0,114,190,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,197,0,0,0,218,2,0,0,115,14,0,0,0,8, - 2,8,8,8,13,8,10,8,7,8,10,14,8,114,197,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,80,0,0,0,101,0,90,1, - 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, - 100,4,100,5,132,0,90,5,100,6,100,7,132,0,90,6, - 101,7,135,0,102,1,100,8,100,9,132,8,131,1,90,8, - 101,7,100,10,100,11,132,0,131,1,90,9,100,12,100,13, - 132,0,90,10,135,0,4,0,90,11,83,0,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,16,0,0,0,124,1,124, - 0,95,0,124,2,124,0,95,1,100,1,83,0,41,2,122, - 75,67,97,99,104,101,32,116,104,101,32,109,111,100,117,108, - 101,32,110,97,109,101,32,97,110,100,32,116,104,101,32,112, - 97,116,104,32,116,111,32,116,104,101,32,102,105,108,101,32, - 102,111,117,110,100,32,98,121,32,116,104,101,10,32,32,32, - 32,32,32,32,32,102,105,110,100,101,114,46,78,41,2,114, - 102,0,0,0,114,37,0,0,0,41,3,114,104,0,0,0, - 114,123,0,0,0,114,37,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,188,0,0,0,111,3, - 0,0,115,4,0,0,0,0,3,6,1,122,19,70,105,108, - 101,76,111,97,100,101,114,46,95,95,105,110,105,116,95,95, - 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, - 0,67,0,0,0,115,24,0,0,0,124,0,106,0,124,1, - 106,0,107,2,111,22,124,0,106,1,124,1,106,1,107,2, - 83,0,41,1,78,41,2,218,9,95,95,99,108,97,115,115, - 95,95,114,115,0,0,0,41,2,114,104,0,0,0,218,5, - 111,116,104,101,114,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,6,95,95,101,113,95,95,117,3,0,0, - 115,4,0,0,0,0,1,12,1,122,17,70,105,108,101,76, - 111,97,100,101,114,46,95,95,101,113,95,95,99,1,0,0, - 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, - 0,115,20,0,0,0,116,0,124,0,106,1,131,1,116,0, - 124,0,106,2,131,1,65,0,83,0,41,1,78,41,3,218, - 4,104,97,115,104,114,102,0,0,0,114,37,0,0,0,41, - 1,114,104,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,8,95,95,104,97,115,104,95,95,121, - 3,0,0,115,2,0,0,0,0,1,122,19,70,105,108,101, - 76,111,97,100,101,114,46,95,95,104,97,115,104,95,95,99, - 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 3,0,0,0,115,16,0,0,0,116,0,116,1,124,0,131, - 2,160,2,124,1,161,1,83,0,41,1,122,100,76,111,97, - 100,32,97,32,109,111,100,117,108,101,32,102,114,111,109,32, - 97,32,102,105,108,101,46,10,10,32,32,32,32,32,32,32, - 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, - 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, - 32,101,120,101,99,95,109,111,100,117,108,101,40,41,32,105, - 110,115,116,101,97,100,46,10,10,32,32,32,32,32,32,32, - 32,41,3,218,5,115,117,112,101,114,114,214,0,0,0,114, - 196,0,0,0,41,2,114,104,0,0,0,114,123,0,0,0, - 41,1,114,215,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,196,0,0,0,124,3,0,0,115,2,0,0,0,0, - 10,122,22,70,105,108,101,76,111,97,100,101,114,46,108,111, - 97,100,95,109,111,100,117,108,101,99,2,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,6, - 0,0,0,124,0,106,0,83,0,41,1,122,58,82,101,116, - 117,114,110,32,116,104,101,32,112,97,116,104,32,116,111,32, - 116,104,101,32,115,111,117,114,99,101,32,102,105,108,101,32, - 97,115,32,102,111,117,110,100,32,98,121,32,116,104,101,32, - 102,105,110,100,101,114,46,41,1,114,37,0,0,0,41,2, - 114,104,0,0,0,114,123,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,161,0,0,0,136,3, - 0,0,115,2,0,0,0,0,3,122,23,70,105,108,101,76, - 111,97,100,101,114,46,103,101,116,95,102,105,108,101,110,97, - 109,101,99,2,0,0,0,0,0,0,0,3,0,0,0,9, - 0,0,0,67,0,0,0,115,32,0,0,0,116,0,160,1, - 124,1,100,1,161,2,143,10,125,2,124,2,160,2,161,0, - 83,0,81,0,82,0,88,0,100,2,83,0,41,3,122,39, - 82,101,116,117,114,110,32,116,104,101,32,100,97,116,97,32, - 102,114,111,109,32,112,97,116,104,32,97,115,32,114,97,119, - 32,98,121,116,101,115,46,218,1,114,78,41,3,114,52,0, - 0,0,114,53,0,0,0,90,4,114,101,97,100,41,3,114, - 104,0,0,0,114,37,0,0,0,114,57,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,202,0, - 0,0,141,3,0,0,115,4,0,0,0,0,2,14,1,122, - 19,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, - 100,97,116,97,41,12,114,109,0,0,0,114,108,0,0,0, - 114,110,0,0,0,114,111,0,0,0,114,188,0,0,0,114, - 217,0,0,0,114,219,0,0,0,114,120,0,0,0,114,196, - 0,0,0,114,161,0,0,0,114,202,0,0,0,90,13,95, - 95,99,108,97,115,115,99,101,108,108,95,95,114,4,0,0, - 0,114,4,0,0,0,41,1,114,215,0,0,0,114,6,0, - 0,0,114,214,0,0,0,106,3,0,0,115,12,0,0,0, - 12,5,8,6,8,4,8,3,16,12,12,5,114,214,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,3,0, - 0,0,64,0,0,0,115,46,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, - 4,100,5,132,0,90,5,100,6,100,7,156,1,100,8,100, - 9,132,2,90,6,100,10,83,0,41,11,218,16,83,111,117, - 114,99,101,70,105,108,101,76,111,97,100,101,114,122,62,67, - 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,83,111,117,114,99,101, - 76,111,97,100,101,114,32,117,115,105,110,103,32,116,104,101, - 32,102,105,108,101,32,115,121,115,116,101,109,46,99,2,0, - 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, - 0,0,115,22,0,0,0,116,0,124,1,131,1,125,2,124, - 2,106,1,124,2,106,2,100,1,156,2,83,0,41,2,122, - 33,82,101,116,117,114,110,32,116,104,101,32,109,101,116,97, - 100,97,116,97,32,102,111,114,32,116,104,101,32,112,97,116, - 104,46,41,2,114,151,0,0,0,114,209,0,0,0,41,3, - 114,41,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,104,0,0,0,114, - 37,0,0,0,114,213,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,114,199,0,0,0,151,3,0, - 0,115,4,0,0,0,0,2,8,1,122,27,83,111,117,114, - 99,101,70,105,108,101,76,111,97,100,101,114,46,112,97,116, - 104,95,115,116,97,116,115,99,4,0,0,0,0,0,0,0, - 5,0,0,0,5,0,0,0,67,0,0,0,115,24,0,0, - 0,116,0,124,1,131,1,125,4,124,0,106,1,124,2,124, - 3,124,4,100,1,141,3,83,0,41,2,78,41,1,218,5, - 95,109,111,100,101,41,2,114,101,0,0,0,114,200,0,0, - 0,41,5,114,104,0,0,0,114,94,0,0,0,114,93,0, - 0,0,114,56,0,0,0,114,44,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,114,201,0,0,0, - 156,3,0,0,115,4,0,0,0,0,2,8,1,122,32,83, - 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,46, - 95,99,97,99,104,101,95,98,121,116,101,99,111,100,101,105, - 182,1,0,0,41,1,114,224,0,0,0,99,3,0,0,0, - 1,0,0,0,9,0,0,0,18,0,0,0,67,0,0,0, - 115,248,0,0,0,116,0,124,1,131,1,92,2,125,4,125, - 5,103,0,125,6,120,38,124,4,114,54,116,1,124,4,131, - 1,115,54,116,0,124,4,131,1,92,2,125,4,125,7,124, - 6,160,2,124,7,161,1,1,0,113,18,87,0,120,108,116, - 3,124,6,131,1,68,0,93,96,125,7,116,4,124,4,124, - 7,131,2,125,4,121,14,116,5,160,6,124,4,161,1,1, - 0,87,0,113,66,4,0,116,7,107,10,114,116,1,0,1, - 0,1,0,119,66,89,0,113,66,4,0,116,8,107,10,114, - 160,1,0,125,8,1,0,122,18,116,9,160,10,100,1,124, - 4,124,8,161,3,1,0,100,2,83,0,100,2,125,8,126, - 8,88,0,113,66,88,0,113,66,87,0,121,28,116,11,124, - 1,124,2,124,3,131,3,1,0,116,9,160,10,100,3,124, - 1,161,2,1,0,87,0,110,48,4,0,116,8,107,10,114, - 242,1,0,125,8,1,0,122,20,116,9,160,10,100,1,124, - 1,124,8,161,3,1,0,87,0,89,0,100,2,100,2,125, - 8,126,8,88,0,110,2,88,0,100,2,83,0,41,4,122, - 27,87,114,105,116,101,32,98,121,116,101,115,32,100,97,116, - 97,32,116,111,32,97,32,102,105,108,101,46,122,27,99,111, - 117,108,100,32,110,111,116,32,99,114,101,97,116,101,32,123, - 33,114,125,58,32,123,33,114,125,78,122,12,99,114,101,97, - 116,101,100,32,123,33,114,125,41,12,114,40,0,0,0,114, - 48,0,0,0,114,167,0,0,0,114,35,0,0,0,114,30, - 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,42,0,0,0,114,118,0,0,0,114,132,0,0,0,114, - 58,0,0,0,41,9,114,104,0,0,0,114,37,0,0,0, - 114,56,0,0,0,114,224,0,0,0,218,6,112,97,114,101, - 110,116,114,98,0,0,0,114,29,0,0,0,114,25,0,0, - 0,114,203,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,114,200,0,0,0,161,3,0,0,115,42, - 0,0,0,0,2,12,1,4,2,14,1,12,1,14,2,14, - 1,10,1,2,1,14,1,14,2,6,1,16,3,6,1,8, - 1,20,1,2,1,12,1,16,1,16,2,8,1,122,25,83, - 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,46, - 115,101,116,95,100,97,116,97,78,41,7,114,109,0,0,0, - 114,108,0,0,0,114,110,0,0,0,114,111,0,0,0,114, - 199,0,0,0,114,201,0,0,0,114,200,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,114,222,0,0,0,147,3,0,0,115,6,0,0,0, - 12,4,8,5,8,5,114,222,0,0,0,99,0,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0, - 115,32,0,0,0,101,0,90,1,100,0,90,2,100,1,90, - 3,100,2,100,3,132,0,90,4,100,4,100,5,132,0,90, - 5,100,6,83,0,41,7,218,20,83,111,117,114,99,101,108, - 101,115,115,70,105,108,101,76,111,97,100,101,114,122,45,76, - 111,97,100,101,114,32,119,104,105,99,104,32,104,97,110,100, - 108,101,115,32,115,111,117,114,99,101,108,101,115,115,32,102, - 105,108,101,32,105,109,112,111,114,116,115,46,99,2,0,0, - 0,0,0,0,0,5,0,0,0,5,0,0,0,67,0,0, - 0,115,68,0,0,0,124,0,160,0,124,1,161,1,125,2, - 124,0,160,1,124,2,161,1,125,3,124,1,124,2,100,1, - 156,2,125,4,116,2,124,3,124,1,124,4,131,3,1,0, - 116,3,116,4,124,3,131,1,100,2,100,0,133,2,25,0, - 124,1,124,2,100,3,141,3,83,0,41,4,78,41,2,114, - 102,0,0,0,114,37,0,0,0,114,128,0,0,0,41,2, - 114,102,0,0,0,114,93,0,0,0,41,5,114,161,0,0, - 0,114,202,0,0,0,114,135,0,0,0,114,147,0,0,0, - 114,210,0,0,0,41,5,114,104,0,0,0,114,123,0,0, - 0,114,37,0,0,0,114,56,0,0,0,114,134,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, - 190,0,0,0,196,3,0,0,115,18,0,0,0,0,1,10, - 1,10,4,2,1,8,2,12,1,2,1,14,1,2,1,122, - 29,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, - 111,97,100,101,114,46,103,101,116,95,99,111,100,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, - 0,0,0,115,4,0,0,0,100,1,83,0,41,2,122,39, - 82,101,116,117,114,110,32,78,111,110,101,32,97,115,32,116, - 104,101,114,101,32,105,115,32,110,111,32,115,111,117,114,99, - 101,32,99,111,100,101,46,78,114,4,0,0,0,41,2,114, - 104,0,0,0,114,123,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,114,204,0,0,0,212,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,109,0,0, - 0,114,108,0,0,0,114,110,0,0,0,114,111,0,0,0, - 114,190,0,0,0,114,204,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,227, - 0,0,0,192,3,0,0,115,4,0,0,0,12,4,8,16, - 114,227,0,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,3,0,0,0,64,0,0,0,115,92,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, - 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, - 0,90,6,100,8,100,9,132,0,90,7,100,10,100,11,132, - 0,90,8,100,12,100,13,132,0,90,9,100,14,100,15,132, - 0,90,10,100,16,100,17,132,0,90,11,101,12,100,18,100, - 19,132,0,131,1,90,13,100,20,83,0,41,21,218,19,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,122,93,76,111,97,100,101,114,32,102,111,114,32,101, - 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,115, - 46,10,10,32,32,32,32,84,104,101,32,99,111,110,115,116, - 114,117,99,116,111,114,32,105,115,32,100,101,115,105,103,110, - 101,100,32,116,111,32,119,111,114,107,32,119,105,116,104,32, - 70,105,108,101,70,105,110,100,101,114,46,10,10,32,32,32, - 32,99,3,0,0,0,0,0,0,0,3,0,0,0,2,0, - 0,0,67,0,0,0,115,16,0,0,0,124,1,124,0,95, - 0,124,2,124,0,95,1,100,0,83,0,41,1,78,41,2, - 114,102,0,0,0,114,37,0,0,0,41,3,114,104,0,0, - 0,114,102,0,0,0,114,37,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,114,188,0,0,0,229, - 3,0,0,115,4,0,0,0,0,1,6,1,122,28,69,120, - 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, - 114,46,95,95,105,110,105,116,95,95,99,2,0,0,0,0, - 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, - 24,0,0,0,124,0,106,0,124,1,106,0,107,2,111,22, - 124,0,106,1,124,1,106,1,107,2,83,0,41,1,78,41, - 2,114,215,0,0,0,114,115,0,0,0,41,2,114,104,0, - 0,0,114,216,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,217,0,0,0,233,3,0,0,115, - 4,0,0,0,0,1,12,1,122,26,69,120,116,101,110,115, - 105,111,110,70,105,108,101,76,111,97,100,101,114,46,95,95, - 101,113,95,95,99,1,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,115,20,0,0,0,116,0, - 124,0,106,1,131,1,116,0,124,0,106,2,131,1,65,0, - 83,0,41,1,78,41,3,114,218,0,0,0,114,102,0,0, - 0,114,37,0,0,0,41,1,114,104,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,219,0,0, - 0,237,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, + 111,100,101,78,41,10,114,107,0,0,0,114,106,0,0,0, + 114,108,0,0,0,114,196,0,0,0,114,197,0,0,0,114, + 199,0,0,0,114,198,0,0,0,114,202,0,0,0,114,206, + 0,0,0,114,188,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,195,0,0, + 0,218,2,0,0,115,14,0,0,0,8,2,8,8,8,13, + 8,10,8,7,8,10,14,8,114,195,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, + 0,0,115,80,0,0,0,101,0,90,1,100,0,90,2,100, + 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, + 0,90,5,100,6,100,7,132,0,90,6,101,7,135,0,102, + 1,100,8,100,9,132,8,131,1,90,8,101,7,100,10,100, + 11,132,0,131,1,90,9,100,12,100,13,132,0,90,10,135, + 0,4,0,90,11,83,0,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,16,0,0,0,124,1,124,0,95,0,124,2, + 124,0,95,1,100,1,83,0,41,2,122,75,67,97,99,104, + 101,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109, + 101,32,97,110,100,32,116,104,101,32,112,97,116,104,32,116, + 111,32,116,104,101,32,102,105,108,101,32,102,111,117,110,100, + 32,98,121,32,116,104,101,10,32,32,32,32,32,32,32,32, + 102,105,110,100,101,114,46,78,41,2,114,100,0,0,0,114, + 35,0,0,0,41,3,114,102,0,0,0,114,121,0,0,0, + 114,35,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,186,0,0,0,111,3,0,0,115,4,0, + 0,0,0,3,6,1,122,19,70,105,108,101,76,111,97,100, + 101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0, + 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, + 115,24,0,0,0,124,0,106,0,124,1,106,0,107,2,111, + 22,124,0,106,1,124,1,106,1,107,2,83,0,41,1,78, + 41,2,218,9,95,95,99,108,97,115,115,95,95,114,113,0, + 0,0,41,2,114,102,0,0,0,218,5,111,116,104,101,114, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 6,95,95,101,113,95,95,117,3,0,0,115,4,0,0,0, + 0,1,12,1,122,17,70,105,108,101,76,111,97,100,101,114, + 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0, + 0,116,0,124,0,106,1,131,1,116,0,124,0,106,2,131, + 1,65,0,83,0,41,1,78,41,3,218,4,104,97,115,104, + 114,100,0,0,0,114,35,0,0,0,41,1,114,102,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,8,95,95,104,97,115,104,95,95,121,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,3,0,0,0,5,0,0,0,67,0,0,0,115, - 36,0,0,0,116,0,160,1,116,2,106,3,124,1,161,2, - 125,2,116,0,160,4,100,1,124,1,106,5,124,0,106,6, - 161,3,1,0,124,2,83,0,41,2,122,38,67,114,101,97, - 116,101,32,97,110,32,117,110,105,116,105,97,108,105,122,101, - 100,32,101,120,116,101,110,115,105,111,110,32,109,111,100,117, - 108,101,122,38,101,120,116,101,110,115,105,111,110,32,109,111, - 100,117,108,101,32,123,33,114,125,32,108,111,97,100,101,100, - 32,102,114,111,109,32,123,33,114,125,41,7,114,118,0,0, - 0,114,191,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,132,0,0,0, - 114,102,0,0,0,114,37,0,0,0,41,3,114,104,0,0, - 0,114,168,0,0,0,114,193,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,114,189,0,0,0,240, - 3,0,0,115,10,0,0,0,0,2,4,1,10,1,6,1, - 12,1,122,33,69,120,116,101,110,115,105,111,110,70,105,108, - 101,76,111,97,100,101,114,46,99,114,101,97,116,101,95,109, - 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,5,0,0,0,67,0,0,0,115,36,0,0,0,116, - 0,160,1,116,2,106,3,124,1,161,2,1,0,116,0,160, - 4,100,1,124,0,106,5,124,0,106,6,161,3,1,0,100, - 2,83,0,41,3,122,30,73,110,105,116,105,97,108,105,122, - 101,32,97,110,32,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,122,40,101,120,116,101,110,115,105,111,110, - 32,109,111,100,117,108,101,32,123,33,114,125,32,101,120,101, - 99,117,116,101,100,32,102,114,111,109,32,123,33,114,125,78, - 41,7,114,118,0,0,0,114,191,0,0,0,114,145,0,0, - 0,90,12,101,120,101,99,95,100,121,110,97,109,105,99,114, - 132,0,0,0,114,102,0,0,0,114,37,0,0,0,41,2, - 114,104,0,0,0,114,193,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,194,0,0,0,248,3, - 0,0,115,6,0,0,0,0,2,14,1,6,1,122,31,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,3, - 0,0,0,115,36,0,0,0,116,0,124,0,106,1,131,1, - 100,1,25,0,137,0,116,2,135,0,102,1,100,2,100,3, - 132,8,116,3,68,0,131,1,131,1,83,0,41,4,122,49, - 82,101,116,117,114,110,32,84,114,117,101,32,105,102,32,116, - 104,101,32,101,120,116,101,110,115,105,111,110,32,109,111,100, - 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, - 46,114,31,0,0,0,99,1,0,0,0,0,0,0,0,2, - 0,0,0,4,0,0,0,51,0,0,0,115,26,0,0,0, - 124,0,93,18,125,1,136,0,100,0,124,1,23,0,107,2, - 86,0,1,0,113,2,100,1,83,0,41,2,114,188,0,0, - 0,78,114,4,0,0,0,41,2,114,24,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,6,0,0,0,250,9,60, - 103,101,110,101,120,112,114,62,1,4,0,0,115,2,0,0, - 0,4,1,122,49,69,120,116,101,110,115,105,111,110,70,105, - 108,101,76,111,97,100,101,114,46,105,115,95,112,97,99,107, - 97,103,101,46,60,108,111,99,97,108,115,62,46,60,103,101, - 110,101,120,112,114,62,41,4,114,40,0,0,0,114,37,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,104,0, - 0,0,114,123,0,0,0,114,4,0,0,0,41,1,114,230, - 0,0,0,114,6,0,0,0,114,163,0,0,0,254,3,0, - 0,115,6,0,0,0,0,2,14,1,12,1,122,30,69,120, - 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, - 114,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,83,0,41,2,122,63,82,101, - 116,117,114,110,32,78,111,110,101,32,97,115,32,97,110,32, - 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 32,99,97,110,110,111,116,32,99,114,101,97,116,101,32,97, - 32,99,111,100,101,32,111,98,106,101,99,116,46,78,114,4, - 0,0,0,41,2,114,104,0,0,0,114,123,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,190, - 0,0,0,4,4,0,0,115,2,0,0,0,0,2,122,28, - 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, - 100,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,83,0,41,2,122,53,82,101, - 116,117,114,110,32,78,111,110,101,32,97,115,32,101,120,116, - 101,110,115,105,111,110,32,109,111,100,117,108,101,115,32,104, - 97,118,101,32,110,111,32,115,111,117,114,99,101,32,99,111, - 100,101,46,78,114,4,0,0,0,41,2,114,104,0,0,0, - 114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,204,0,0,0,8,4,0,0,115,2,0, - 0,0,0,2,122,30,69,120,116,101,110,115,105,111,110,70, - 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, - 117,114,99,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115, + 16,0,0,0,116,0,116,1,124,0,131,2,160,2,124,1, + 161,1,83,0,41,1,122,100,76,111,97,100,32,97,32,109, + 111,100,117,108,101,32,102,114,111,109,32,97,32,102,105,108, + 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, + 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, + 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, + 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, + 100,46,10,10,32,32,32,32,32,32,32,32,41,3,218,5, + 115,117,112,101,114,114,212,0,0,0,114,194,0,0,0,41, + 2,114,102,0,0,0,114,121,0,0,0,41,1,114,213,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,194,0,0, + 0,124,3,0,0,115,2,0,0,0,0,10,122,22,70,105, + 108,101,76,111,97,100,101,114,46,108,111,97,100,95,109,111, + 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, 0,1,0,0,0,67,0,0,0,115,6,0,0,0,124,0, 106,0,83,0,41,1,122,58,82,101,116,117,114,110,32,116, 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, 111,117,114,99,101,32,102,105,108,101,32,97,115,32,102,111, 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, - 114,46,41,1,114,37,0,0,0,41,2,114,104,0,0,0, - 114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,161,0,0,0,12,4,0,0,115,2,0, - 0,0,0,3,122,32,69,120,116,101,110,115,105,111,110,70, - 105,108,101,76,111,97,100,101,114,46,103,101,116,95,102,105, - 108,101,110,97,109,101,78,41,14,114,109,0,0,0,114,108, - 0,0,0,114,110,0,0,0,114,111,0,0,0,114,188,0, - 0,0,114,217,0,0,0,114,219,0,0,0,114,189,0,0, - 0,114,194,0,0,0,114,163,0,0,0,114,190,0,0,0, - 114,204,0,0,0,114,120,0,0,0,114,161,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,114,228,0,0,0,221,3,0,0,115,18,0,0, - 0,12,8,8,4,8,4,8,3,8,8,8,6,8,6,8, - 4,8,4,114,228,0,0,0,99,0,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,64,0,0,0,115,96,0, - 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, - 100,3,132,0,90,4,100,4,100,5,132,0,90,5,100,6, - 100,7,132,0,90,6,100,8,100,9,132,0,90,7,100,10, - 100,11,132,0,90,8,100,12,100,13,132,0,90,9,100,14, - 100,15,132,0,90,10,100,16,100,17,132,0,90,11,100,18, - 100,19,132,0,90,12,100,20,100,21,132,0,90,13,100,22, - 83,0,41,23,218,14,95,78,97,109,101,115,112,97,99,101, - 80,97,116,104,97,38,1,0,0,82,101,112,114,101,115,101, - 110,116,115,32,97,32,110,97,109,101,115,112,97,99,101,32, - 112,97,99,107,97,103,101,39,115,32,112,97,116,104,46,32, - 32,73,116,32,117,115,101,115,32,116,104,101,32,109,111,100, - 117,108,101,32,110,97,109,101,10,32,32,32,32,116,111,32, - 102,105,110,100,32,105,116,115,32,112,97,114,101,110,116,32, - 109,111,100,117,108,101,44,32,97,110,100,32,102,114,111,109, - 32,116,104,101,114,101,32,105,116,32,108,111,111,107,115,32, - 117,112,32,116,104,101,32,112,97,114,101,110,116,39,115,10, - 32,32,32,32,95,95,112,97,116,104,95,95,46,32,32,87, - 104,101,110,32,116,104,105,115,32,99,104,97,110,103,101,115, - 44,32,116,104,101,32,109,111,100,117,108,101,39,115,32,111, - 119,110,32,112,97,116,104,32,105,115,32,114,101,99,111,109, - 112,117,116,101,100,44,10,32,32,32,32,117,115,105,110,103, - 32,112,97,116,104,95,102,105,110,100,101,114,46,32,32,70, - 111,114,32,116,111,112,45,108,101,118,101,108,32,109,111,100, - 117,108,101,115,44,32,116,104,101,32,112,97,114,101,110,116, - 32,109,111,100,117,108,101,39,115,32,112,97,116,104,10,32, - 32,32,32,105,115,32,115,121,115,46,112,97,116,104,46,99, - 4,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, - 67,0,0,0,115,36,0,0,0,124,1,124,0,95,0,124, - 2,124,0,95,1,116,2,124,0,160,3,161,0,131,1,124, - 0,95,4,124,3,124,0,95,5,100,0,83,0,41,1,78, - 41,6,218,5,95,110,97,109,101,218,5,95,112,97,116,104, - 114,97,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,104,0,0,0,114, - 102,0,0,0,114,37,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,6,0,0,0,114,188,0,0,0,25,4,0,0,115,8, - 0,0,0,0,1,6,1,6,1,14,1,122,23,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,95,95,105,110, - 105,116,95,95,99,1,0,0,0,0,0,0,0,4,0,0, - 0,3,0,0,0,67,0,0,0,115,38,0,0,0,124,0, - 106,0,160,1,100,1,161,1,92,3,125,1,125,2,125,3, - 124,2,100,2,107,2,114,30,100,6,83,0,124,1,100,5, - 102,2,83,0,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,61,0,0,0,114,32,0,0,0, - 114,8,0,0,0,114,37,0,0,0,90,8,95,95,112,97, - 116,104,95,95,41,2,114,8,0,0,0,114,37,0,0,0, - 41,2,114,235,0,0,0,114,34,0,0,0,41,4,114,104, - 0,0,0,114,226,0,0,0,218,3,100,111,116,90,2,109, - 101,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 218,23,95,102,105,110,100,95,112,97,114,101,110,116,95,112, - 97,116,104,95,110,97,109,101,115,31,4,0,0,115,8,0, - 0,0,0,2,18,1,8,2,4,3,122,38,95,78,97,109, - 101,115,112,97,99,101,80,97,116,104,46,95,102,105,110,100, - 95,112,97,114,101,110,116,95,112,97,116,104,95,110,97,109, - 101,115,99,1,0,0,0,0,0,0,0,3,0,0,0,3, - 0,0,0,67,0,0,0,115,28,0,0,0,124,0,160,0, - 161,0,92,2,125,1,125,2,116,1,116,2,106,3,124,1, - 25,0,124,2,131,2,83,0,41,1,78,41,4,114,242,0, - 0,0,114,114,0,0,0,114,8,0,0,0,218,7,109,111, - 100,117,108,101,115,41,3,114,104,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,6,0,0,0,114, - 237,0,0,0,41,4,0,0,115,4,0,0,0,0,1,12, - 1,122,31,95,78,97,109,101,115,112,97,99,101,80,97,116, - 104,46,95,103,101,116,95,112,97,114,101,110,116,95,112,97, - 116,104,99,1,0,0,0,0,0,0,0,3,0,0,0,4, - 0,0,0,67,0,0,0,115,80,0,0,0,116,0,124,0, - 160,1,161,0,131,1,125,1,124,1,124,0,106,2,107,3, - 114,74,124,0,160,3,124,0,106,4,124,1,161,2,125,2, - 124,2,100,0,107,9,114,68,124,2,106,5,100,0,107,8, - 114,68,124,2,106,6,114,68,124,2,106,6,124,0,95,7, - 124,1,124,0,95,2,124,0,106,7,83,0,41,1,78,41, - 8,114,97,0,0,0,114,237,0,0,0,114,238,0,0,0, - 114,239,0,0,0,114,235,0,0,0,114,124,0,0,0,114, - 160,0,0,0,114,236,0,0,0,41,3,114,104,0,0,0, - 90,11,112,97,114,101,110,116,95,112,97,116,104,114,168,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,218,12,95,114,101,99,97,108,99,117,108,97,116,101,45, - 4,0,0,115,16,0,0,0,0,2,12,1,10,1,14,3, - 18,1,6,1,8,1,6,1,122,27,95,78,97,109,101,115, - 112,97,99,101,80,97,116,104,46,95,114,101,99,97,108,99, - 117,108,97,116,101,99,1,0,0,0,0,0,0,0,1,0, - 0,0,3,0,0,0,67,0,0,0,115,12,0,0,0,116, - 0,124,0,160,1,161,0,131,1,83,0,41,1,78,41,2, - 218,4,105,116,101,114,114,244,0,0,0,41,1,114,104,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,218,8,95,95,105,116,101,114,95,95,58,4,0,0,115, - 2,0,0,0,0,1,122,23,95,78,97,109,101,115,112,97, - 99,101,80,97,116,104,46,95,95,105,116,101,114,95,95,99, - 3,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, - 67,0,0,0,115,14,0,0,0,124,2,124,0,106,0,124, - 1,60,0,100,0,83,0,41,1,78,41,1,114,236,0,0, - 0,41,3,114,104,0,0,0,218,5,105,110,100,101,120,114, - 37,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,218,11,95,95,115,101,116,105,116,101,109,95,95, - 61,4,0,0,115,2,0,0,0,0,1,122,26,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,95,95,115,101, - 116,105,116,101,109,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,12,0,0, - 0,116,0,124,0,160,1,161,0,131,1,83,0,41,1,78, - 41,2,114,33,0,0,0,114,244,0,0,0,41,1,114,104, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,218,7,95,95,108,101,110,95,95,64,4,0,0,115, - 2,0,0,0,0,1,122,22,95,78,97,109,101,115,112,97, - 99,101,80,97,116,104,46,95,95,108,101,110,95,95,99,1, - 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, - 0,0,0,115,12,0,0,0,100,1,160,0,124,0,106,1, - 161,1,83,0,41,2,78,122,20,95,78,97,109,101,115,112, - 97,99,101,80,97,116,104,40,123,33,114,125,41,41,2,114, - 50,0,0,0,114,236,0,0,0,41,1,114,104,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218, - 8,95,95,114,101,112,114,95,95,67,4,0,0,115,2,0, - 0,0,0,1,122,23,95,78,97,109,101,115,112,97,99,101, - 80,97,116,104,46,95,95,114,101,112,114,95,95,99,2,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,0, - 0,0,115,12,0,0,0,124,1,124,0,160,0,161,0,107, - 6,83,0,41,1,78,41,1,114,244,0,0,0,41,2,114, - 104,0,0,0,218,4,105,116,101,109,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,218,12,95,95,99,111,110, - 116,97,105,110,115,95,95,70,4,0,0,115,2,0,0,0, - 0,1,122,27,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,46,95,95,99,111,110,116,97,105,110,115,95,95,99, - 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 67,0,0,0,115,16,0,0,0,124,0,106,0,160,1,124, - 1,161,1,1,0,100,0,83,0,41,1,78,41,2,114,236, - 0,0,0,114,167,0,0,0,41,2,114,104,0,0,0,114, - 251,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,114,167,0,0,0,73,4,0,0,115,2,0,0, - 0,0,1,122,21,95,78,97,109,101,115,112,97,99,101,80, - 97,116,104,46,97,112,112,101,110,100,78,41,14,114,109,0, - 0,0,114,108,0,0,0,114,110,0,0,0,114,111,0,0, - 0,114,188,0,0,0,114,242,0,0,0,114,237,0,0,0, - 114,244,0,0,0,114,246,0,0,0,114,248,0,0,0,114, - 249,0,0,0,114,250,0,0,0,114,252,0,0,0,114,167, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,114,234,0,0,0,18,4,0,0, - 115,20,0,0,0,12,7,8,6,8,10,8,4,8,13,8, - 3,8,3,8,3,8,3,8,3,114,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,80,0,0,0,101,0,90,1,100,0,90,2, - 100,1,100,2,132,0,90,3,101,4,100,3,100,4,132,0, - 131,1,90,5,100,5,100,6,132,0,90,6,100,7,100,8, - 132,0,90,7,100,9,100,10,132,0,90,8,100,11,100,12, - 132,0,90,9,100,13,100,14,132,0,90,10,100,15,100,16, - 132,0,90,11,100,17,83,0,41,18,218,16,95,78,97,109, - 101,115,112,97,99,101,76,111,97,100,101,114,99,4,0,0, - 0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0, - 0,115,18,0,0,0,116,0,124,1,124,2,124,3,131,3, - 124,0,95,1,100,0,83,0,41,1,78,41,2,114,234,0, - 0,0,114,236,0,0,0,41,4,114,104,0,0,0,114,102, - 0,0,0,114,37,0,0,0,114,240,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,188,0,0, - 0,79,4,0,0,115,2,0,0,0,0,1,122,25,95,78, - 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,95, - 95,105,110,105,116,95,95,99,2,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,115,12,0,0, - 0,100,1,160,0,124,1,106,1,161,1,83,0,41,2,122, - 115,82,101,116,117,114,110,32,114,101,112,114,32,102,111,114, - 32,116,104,101,32,109,111,100,117,108,101,46,10,10,32,32, - 32,32,32,32,32,32,84,104,101,32,109,101,116,104,111,100, - 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, - 32,84,104,101,32,105,109,112,111,114,116,32,109,97,99,104, - 105,110,101,114,121,32,100,111,101,115,32,116,104,101,32,106, - 111,98,32,105,116,115,101,108,102,46,10,10,32,32,32,32, - 32,32,32,32,122,25,60,109,111,100,117,108,101,32,123,33, - 114,125,32,40,110,97,109,101,115,112,97,99,101,41,62,41, - 2,114,50,0,0,0,114,109,0,0,0,41,2,114,174,0, - 0,0,114,193,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,11,109,111,100,117,108,101,95,114, - 101,112,114,82,4,0,0,115,2,0,0,0,0,7,122,28, - 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, - 46,109,111,100,117,108,101,95,114,101,112,114,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,83,0,41,2,78,84,114,4, - 0,0,0,41,2,114,104,0,0,0,114,123,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,163, - 0,0,0,91,4,0,0,115,2,0,0,0,0,1,122,27, - 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, - 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, - 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, - 115,4,0,0,0,100,1,83,0,41,2,78,114,32,0,0, - 0,114,4,0,0,0,41,2,114,104,0,0,0,114,123,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,204,0,0,0,94,4,0,0,115,2,0,0,0,0, - 1,122,27,95,78,97,109,101,115,112,97,99,101,76,111,97, - 100,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, - 0,0,0,115,16,0,0,0,116,0,100,1,100,2,100,3, - 100,4,100,5,141,4,83,0,41,6,78,114,32,0,0,0, - 122,8,60,115,116,114,105,110,103,62,114,192,0,0,0,84, - 41,1,114,206,0,0,0,41,1,114,207,0,0,0,41,2, - 114,104,0,0,0,114,123,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,190,0,0,0,97,4, - 0,0,115,2,0,0,0,0,1,122,25,95,78,97,109,101, - 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, - 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, - 83,0,41,2,122,42,85,115,101,32,100,101,102,97,117,108, - 116,32,115,101,109,97,110,116,105,99,115,32,102,111,114,32, - 109,111,100,117,108,101,32,99,114,101,97,116,105,111,110,46, - 78,114,4,0,0,0,41,2,114,104,0,0,0,114,168,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,189,0,0,0,100,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, + 114,46,41,1,114,35,0,0,0,41,2,114,102,0,0,0, + 114,121,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,159,0,0,0,136,3,0,0,115,2,0, + 0,0,0,3,122,23,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0, + 0,0,0,0,0,0,3,0,0,0,9,0,0,0,67,0, + 0,0,115,32,0,0,0,116,0,160,1,124,1,100,1,161, + 2,143,10,125,2,124,2,160,2,161,0,83,0,81,0,82, + 0,88,0,100,2,83,0,41,3,122,39,82,101,116,117,114, + 110,32,116,104,101,32,100,97,116,97,32,102,114,111,109,32, + 112,97,116,104,32,97,115,32,114,97,119,32,98,121,116,101, + 115,46,218,1,114,78,41,3,114,50,0,0,0,114,51,0, + 0,0,90,4,114,101,97,100,41,3,114,102,0,0,0,114, + 35,0,0,0,114,55,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,200,0,0,0,141,3,0, + 0,115,4,0,0,0,0,2,14,1,122,19,70,105,108,101, + 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,41, + 12,114,107,0,0,0,114,106,0,0,0,114,108,0,0,0, + 114,109,0,0,0,114,186,0,0,0,114,215,0,0,0,114, + 217,0,0,0,114,118,0,0,0,114,194,0,0,0,114,159, + 0,0,0,114,200,0,0,0,90,13,95,95,99,108,97,115, + 115,99,101,108,108,95,95,114,2,0,0,0,114,2,0,0, + 0,41,1,114,213,0,0,0,114,4,0,0,0,114,212,0, + 0,0,106,3,0,0,115,12,0,0,0,12,5,8,6,8, + 4,8,3,16,12,12,5,114,212,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, + 0,115,46,0,0,0,101,0,90,1,100,0,90,2,100,1, + 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, + 90,5,100,6,100,7,156,1,100,8,100,9,132,2,90,6, + 100,10,83,0,41,11,218,16,83,111,117,114,99,101,70,105, + 108,101,76,111,97,100,101,114,122,62,67,111,110,99,114,101, + 116,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111, + 110,32,111,102,32,83,111,117,114,99,101,76,111,97,100,101, + 114,32,117,115,105,110,103,32,116,104,101,32,102,105,108,101, + 32,115,121,115,116,101,109,46,99,2,0,0,0,0,0,0, + 0,3,0,0,0,3,0,0,0,67,0,0,0,115,22,0, + 0,0,116,0,124,1,131,1,125,2,124,2,106,1,124,2, + 106,2,100,1,156,2,83,0,41,2,122,33,82,101,116,117, + 114,110,32,116,104,101,32,109,101,116,97,100,97,116,97,32, + 102,111,114,32,116,104,101,32,112,97,116,104,46,41,2,114, + 149,0,0,0,114,207,0,0,0,41,3,114,39,0,0,0, + 218,8,115,116,95,109,116,105,109,101,90,7,115,116,95,115, + 105,122,101,41,3,114,102,0,0,0,114,35,0,0,0,114, + 211,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,197,0,0,0,151,3,0,0,115,4,0,0, + 0,0,2,8,1,122,27,83,111,117,114,99,101,70,105,108, + 101,76,111,97,100,101,114,46,112,97,116,104,95,115,116,97, + 116,115,99,4,0,0,0,0,0,0,0,5,0,0,0,5, + 0,0,0,67,0,0,0,115,24,0,0,0,116,0,124,1, + 131,1,125,4,124,0,106,1,124,2,124,3,124,4,100,1, + 141,3,83,0,41,2,78,41,1,218,5,95,109,111,100,101, + 41,2,114,99,0,0,0,114,198,0,0,0,41,5,114,102, + 0,0,0,114,92,0,0,0,114,91,0,0,0,114,54,0, + 0,0,114,42,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,199,0,0,0,156,3,0,0,115, + 4,0,0,0,0,2,8,1,122,32,83,111,117,114,99,101, + 70,105,108,101,76,111,97,100,101,114,46,95,99,97,99,104, + 101,95,98,121,116,101,99,111,100,101,105,182,1,0,0,41, + 1,114,222,0,0,0,99,3,0,0,0,1,0,0,0,9, + 0,0,0,18,0,0,0,67,0,0,0,115,248,0,0,0, + 116,0,124,1,131,1,92,2,125,4,125,5,103,0,125,6, + 120,38,124,4,114,54,116,1,124,4,131,1,115,54,116,0, + 124,4,131,1,92,2,125,4,125,7,124,6,160,2,124,7, + 161,1,1,0,113,18,87,0,120,108,116,3,124,6,131,1, + 68,0,93,96,125,7,116,4,124,4,124,7,131,2,125,4, + 121,14,116,5,160,6,124,4,161,1,1,0,87,0,113,66, + 4,0,116,7,107,10,114,116,1,0,1,0,1,0,119,66, + 89,0,113,66,4,0,116,8,107,10,114,160,1,0,125,8, + 1,0,122,18,116,9,160,10,100,1,124,4,124,8,161,3, + 1,0,100,2,83,0,100,2,125,8,126,8,88,0,113,66, + 88,0,113,66,87,0,121,28,116,11,124,1,124,2,124,3, + 131,3,1,0,116,9,160,10,100,3,124,1,161,2,1,0, + 87,0,110,48,4,0,116,8,107,10,114,242,1,0,125,8, + 1,0,122,20,116,9,160,10,100,1,124,1,124,8,161,3, + 1,0,87,0,89,0,100,2,100,2,125,8,126,8,88,0, + 110,2,88,0,100,2,83,0,41,4,122,27,87,114,105,116, + 101,32,98,121,116,101,115,32,100,97,116,97,32,116,111,32, + 97,32,102,105,108,101,46,122,27,99,111,117,108,100,32,110, + 111,116,32,99,114,101,97,116,101,32,123,33,114,125,58,32, + 123,33,114,125,78,122,12,99,114,101,97,116,101,100,32,123, + 33,114,125,41,12,114,38,0,0,0,114,46,0,0,0,114, + 165,0,0,0,114,33,0,0,0,114,28,0,0,0,114,1, + 0,0,0,90,5,109,107,100,105,114,218,15,70,105,108,101, + 69,120,105,115,116,115,69,114,114,111,114,114,40,0,0,0, + 114,116,0,0,0,114,130,0,0,0,114,56,0,0,0,41, + 9,114,102,0,0,0,114,35,0,0,0,114,54,0,0,0, + 114,222,0,0,0,218,6,112,97,114,101,110,116,114,96,0, + 0,0,114,27,0,0,0,114,23,0,0,0,114,201,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,198,0,0,0,161,3,0,0,115,42,0,0,0,0,2, + 12,1,4,2,14,1,12,1,14,2,14,1,10,1,2,1, + 14,1,14,2,6,1,16,3,6,1,8,1,20,1,2,1, + 12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,101, + 70,105,108,101,76,111,97,100,101,114,46,115,101,116,95,100, + 97,116,97,78,41,7,114,107,0,0,0,114,106,0,0,0, + 114,108,0,0,0,114,109,0,0,0,114,197,0,0,0,114, + 199,0,0,0,114,198,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,220,0, + 0,0,147,3,0,0,115,6,0,0,0,12,4,8,5,8, + 5,114,220,0,0,0,99,0,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,64,0,0,0,115,32,0,0,0, + 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, + 132,0,90,4,100,4,100,5,132,0,90,5,100,6,83,0, + 41,7,218,20,83,111,117,114,99,101,108,101,115,115,70,105, + 108,101,76,111,97,100,101,114,122,45,76,111,97,100,101,114, + 32,119,104,105,99,104,32,104,97,110,100,108,101,115,32,115, + 111,117,114,99,101,108,101,115,115,32,102,105,108,101,32,105, + 109,112,111,114,116,115,46,99,2,0,0,0,0,0,0,0, + 5,0,0,0,5,0,0,0,67,0,0,0,115,68,0,0, + 0,124,0,160,0,124,1,161,1,125,2,124,0,160,1,124, + 2,161,1,125,3,124,1,124,2,100,1,156,2,125,4,116, + 2,124,3,124,1,124,4,131,3,1,0,116,3,116,4,124, + 3,131,1,100,2,100,0,133,2,25,0,124,1,124,2,100, + 3,141,3,83,0,41,4,78,41,2,114,100,0,0,0,114, + 35,0,0,0,114,126,0,0,0,41,2,114,100,0,0,0, + 114,91,0,0,0,41,5,114,159,0,0,0,114,200,0,0, + 0,114,133,0,0,0,114,145,0,0,0,114,208,0,0,0, + 41,5,114,102,0,0,0,114,121,0,0,0,114,35,0,0, + 0,114,54,0,0,0,114,132,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,188,0,0,0,196, + 3,0,0,115,18,0,0,0,0,1,10,1,10,4,2,1, + 8,2,12,1,2,1,14,1,2,1,122,29,83,111,117,114, + 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,99,111,100,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, + 0,0,0,100,1,83,0,41,2,122,39,82,101,116,117,114, + 110,32,78,111,110,101,32,97,115,32,116,104,101,114,101,32, + 105,115,32,110,111,32,115,111,117,114,99,101,32,99,111,100, + 101,46,78,114,2,0,0,0,41,2,114,102,0,0,0,114, + 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,202,0,0,0,212,3,0,0,115,2,0,0, + 0,0,2,122,31,83,111,117,114,99,101,108,101,115,115,70, + 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, + 117,114,99,101,78,41,6,114,107,0,0,0,114,106,0,0, + 0,114,108,0,0,0,114,109,0,0,0,114,188,0,0,0, + 114,202,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,225,0,0,0,192,3, + 0,0,115,4,0,0,0,12,4,8,16,114,225,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,64,0,0,0,115,92,0,0,0,101,0,90,1,100,0, + 90,2,100,1,90,3,100,2,100,3,132,0,90,4,100,4, + 100,5,132,0,90,5,100,6,100,7,132,0,90,6,100,8, + 100,9,132,0,90,7,100,10,100,11,132,0,90,8,100,12, + 100,13,132,0,90,9,100,14,100,15,132,0,90,10,100,16, + 100,17,132,0,90,11,101,12,100,18,100,19,132,0,131,1, + 90,13,100,20,83,0,41,21,218,19,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,122,93,76, + 111,97,100,101,114,32,102,111,114,32,101,120,116,101,110,115, + 105,111,110,32,109,111,100,117,108,101,115,46,10,10,32,32, + 32,32,84,104,101,32,99,111,110,115,116,114,117,99,116,111, + 114,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111, + 32,119,111,114,107,32,119,105,116,104,32,70,105,108,101,70, + 105,110,100,101,114,46,10,10,32,32,32,32,99,3,0,0, + 0,0,0,0,0,3,0,0,0,2,0,0,0,67,0,0, + 0,115,16,0,0,0,124,1,124,0,95,0,124,2,124,0, + 95,1,100,0,83,0,41,1,78,41,2,114,100,0,0,0, + 114,35,0,0,0,41,3,114,102,0,0,0,114,100,0,0, + 0,114,35,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,186,0,0,0,229,3,0,0,115,4, + 0,0,0,0,1,6,1,122,28,69,120,116,101,110,115,105, + 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,105, + 110,105,116,95,95,99,2,0,0,0,0,0,0,0,2,0, + 0,0,2,0,0,0,67,0,0,0,115,24,0,0,0,124, + 0,106,0,124,1,106,0,107,2,111,22,124,0,106,1,124, + 1,106,1,107,2,83,0,41,1,78,41,2,114,213,0,0, + 0,114,113,0,0,0,41,2,114,102,0,0,0,114,214,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,215,0,0,0,233,3,0,0,115,4,0,0,0,0, + 1,12,1,122,26,69,120,116,101,110,115,105,111,110,70,105, + 108,101,76,111,97,100,101,114,46,95,95,101,113,95,95,99, + 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,115,20,0,0,0,116,0,124,0,106,1,131, + 1,116,0,124,0,106,2,131,1,65,0,83,0,41,1,78, + 41,3,114,216,0,0,0,114,100,0,0,0,114,35,0,0, + 0,41,1,114,102,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,114,217,0,0,0,237,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,5,0,0,0,67,0,0,0,115,36,0,0,0,116, + 0,160,1,116,2,106,3,124,1,161,2,125,2,116,0,160, + 4,100,1,124,1,106,5,124,0,106,6,161,3,1,0,124, + 2,83,0,41,2,122,38,67,114,101,97,116,101,32,97,110, + 32,117,110,105,116,105,97,108,105,122,101,100,32,101,120,116, + 101,110,115,105,111,110,32,109,111,100,117,108,101,122,38,101, + 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,32, + 123,33,114,125,32,108,111,97,100,101,100,32,102,114,111,109, + 32,123,33,114,125,41,7,114,116,0,0,0,114,189,0,0, + 0,114,143,0,0,0,90,14,99,114,101,97,116,101,95,100, + 121,110,97,109,105,99,114,130,0,0,0,114,100,0,0,0, + 114,35,0,0,0,41,3,114,102,0,0,0,114,166,0,0, + 0,114,191,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,187,0,0,0,240,3,0,0,115,10, + 0,0,0,0,2,4,1,10,1,6,1,12,1,122,33,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,46,99,114,101,97,116,101,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,5,0,0, + 0,67,0,0,0,115,36,0,0,0,116,0,160,1,116,2, + 106,3,124,1,161,2,1,0,116,0,160,4,100,1,124,0, + 106,5,124,0,106,6,161,3,1,0,100,2,83,0,41,3, + 122,30,73,110,105,116,105,97,108,105,122,101,32,97,110,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, + 122,40,101,120,116,101,110,115,105,111,110,32,109,111,100,117, + 108,101,32,123,33,114,125,32,101,120,101,99,117,116,101,100, + 32,102,114,111,109,32,123,33,114,125,78,41,7,114,116,0, + 0,0,114,189,0,0,0,114,143,0,0,0,90,12,101,120, + 101,99,95,100,121,110,97,109,105,99,114,130,0,0,0,114, + 100,0,0,0,114,35,0,0,0,41,2,114,102,0,0,0, + 114,191,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,192,0,0,0,248,3,0,0,115,6,0, + 0,0,0,2,14,1,6,1,122,31,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,101,120, + 101,99,95,109,111,100,117,108,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,4,0,0,0,3,0,0,0,115,36, + 0,0,0,116,0,124,0,106,1,131,1,100,1,25,0,137, + 0,116,2,135,0,102,1,100,2,100,3,132,8,116,3,68, + 0,131,1,131,1,83,0,41,4,122,49,82,101,116,117,114, + 110,32,84,114,117,101,32,105,102,32,116,104,101,32,101,120, + 116,101,110,115,105,111,110,32,109,111,100,117,108,101,32,105, + 115,32,97,32,112,97,99,107,97,103,101,46,114,29,0,0, + 0,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,51,0,0,0,115,26,0,0,0,124,0,93,18,125, + 1,136,0,100,0,124,1,23,0,107,2,86,0,1,0,113, + 2,100,1,83,0,41,2,114,186,0,0,0,78,114,2,0, + 0,0,41,2,114,22,0,0,0,218,6,115,117,102,102,105, + 120,41,1,218,9,102,105,108,101,95,110,97,109,101,114,2, + 0,0,0,114,4,0,0,0,250,9,60,103,101,110,101,120, + 112,114,62,1,4,0,0,115,2,0,0,0,4,1,122,49, + 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, + 100,101,114,46,105,115,95,112,97,99,107,97,103,101,46,60, + 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, + 62,41,4,114,38,0,0,0,114,35,0,0,0,218,3,97, + 110,121,218,18,69,88,84,69,78,83,73,79,78,95,83,85, + 70,70,73,88,69,83,41,2,114,102,0,0,0,114,121,0, + 0,0,114,2,0,0,0,41,1,114,228,0,0,0,114,4, + 0,0,0,114,161,0,0,0,254,3,0,0,115,6,0,0, + 0,0,2,14,1,12,1,122,30,69,120,116,101,110,115,105, + 111,110,70,105,108,101,76,111,97,100,101,114,46,105,115,95, + 112,97,99,107,97,103,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,1,83,0,41,2,122,63,82,101,116,117,114,110,32, + 78,111,110,101,32,97,115,32,97,110,32,101,120,116,101,110, + 115,105,111,110,32,109,111,100,117,108,101,32,99,97,110,110, + 111,116,32,99,114,101,97,116,101,32,97,32,99,111,100,101, + 32,111,98,106,101,99,116,46,78,114,2,0,0,0,41,2, + 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,188,0,0,0,4,4, + 0,0,115,2,0,0,0,0,2,122,28,69,120,116,101,110, + 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,103, + 101,116,95,99,111,100,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,1,83,0,41,2,122,53,82,101,116,117,114,110,32, + 78,111,110,101,32,97,115,32,101,120,116,101,110,115,105,111, + 110,32,109,111,100,117,108,101,115,32,104,97,118,101,32,110, + 111,32,115,111,117,114,99,101,32,99,111,100,101,46,78,114, + 2,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 202,0,0,0,8,4,0,0,115,2,0,0,0,0,2,122, + 30,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, + 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,99, 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,0,83,0,41,1,78, - 114,4,0,0,0,41,2,114,104,0,0,0,114,193,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 114,194,0,0,0,103,4,0,0,115,2,0,0,0,0,1, - 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, - 0,0,0,115,26,0,0,0,116,0,160,1,100,1,124,0, - 106,2,161,2,1,0,116,0,160,3,124,0,124,1,161,2, - 83,0,41,2,122,98,76,111,97,100,32,97,32,110,97,109, - 101,115,112,97,99,101,32,109,111,100,117,108,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, - 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, - 32,32,32,32,32,32,32,32,122,38,110,97,109,101,115,112, - 97,99,101,32,109,111,100,117,108,101,32,108,111,97,100,101, - 100,32,119,105,116,104,32,112,97,116,104,32,123,33,114,125, - 41,4,114,118,0,0,0,114,132,0,0,0,114,236,0,0, - 0,114,195,0,0,0,41,2,114,104,0,0,0,114,123,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,196,0,0,0,106,4,0,0,115,6,0,0,0,0, - 7,6,1,8,1,122,28,95,78,97,109,101,115,112,97,99, - 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, - 117,108,101,78,41,12,114,109,0,0,0,114,108,0,0,0, - 114,110,0,0,0,114,188,0,0,0,114,186,0,0,0,114, - 254,0,0,0,114,163,0,0,0,114,204,0,0,0,114,190, - 0,0,0,114,189,0,0,0,114,194,0,0,0,114,196,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,253,0,0,0,78,4,0,0,115, - 16,0,0,0,8,1,8,3,12,9,8,3,8,3,8,3, - 8,3,8,3,114,253,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,90,1,100,0,90,2,100,1,90,3,101, - 4,100,2,100,3,132,0,131,1,90,5,101,4,100,4,100, - 5,132,0,131,1,90,6,101,4,100,6,100,7,132,0,131, - 1,90,7,101,4,100,8,100,9,132,0,131,1,90,8,101, - 4,100,17,100,11,100,12,132,1,131,1,90,9,101,4,100, - 18,100,13,100,14,132,1,131,1,90,10,101,4,100,19,100, - 15,100,16,132,1,131,1,90,11,100,10,83,0,41,20,218, - 10,80,97,116,104,70,105,110,100,101,114,122,62,77,101,116, - 97,32,112,97,116,104,32,102,105,110,100,101,114,32,102,111, - 114,32,115,121,115,46,112,97,116,104,32,97,110,100,32,112, - 97,99,107,97,103,101,32,95,95,112,97,116,104,95,95,32, - 97,116,116,114,105,98,117,116,101,115,46,99,1,0,0,0, - 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, - 115,42,0,0,0,120,36,116,0,106,1,160,2,161,0,68, - 0,93,22,125,1,116,3,124,1,100,1,131,2,114,12,124, - 1,160,4,161,0,1,0,113,12,87,0,100,2,83,0,41, - 3,122,125,67,97,108,108,32,116,104,101,32,105,110,118,97, - 108,105,100,97,116,101,95,99,97,99,104,101,115,40,41,32, - 109,101,116,104,111,100,32,111,110,32,97,108,108,32,112,97, - 116,104,32,101,110,116,114,121,32,102,105,110,100,101,114,115, - 10,32,32,32,32,32,32,32,32,115,116,111,114,101,100,32, - 105,110,32,115,121,115,46,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,115,32,40,119,104,101, - 114,101,32,105,109,112,108,101,109,101,110,116,101,100,41,46, - 218,17,105,110,118,97,108,105,100,97,116,101,95,99,97,99, - 104,101,115,78,41,5,114,8,0,0,0,218,19,112,97,116, - 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, - 218,6,118,97,108,117,101,115,114,112,0,0,0,114,0,1, - 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,6,0,0,0, - 114,0,1,0,0,124,4,0,0,115,6,0,0,0,0,4, - 16,1,10,1,122,28,80,97,116,104,70,105,110,100,101,114, + 67,0,0,0,115,6,0,0,0,124,0,106,0,83,0,41, + 1,122,58,82,101,116,117,114,110,32,116,104,101,32,112,97, + 116,104,32,116,111,32,116,104,101,32,115,111,117,114,99,101, + 32,102,105,108,101,32,97,115,32,102,111,117,110,100,32,98, + 121,32,116,104,101,32,102,105,110,100,101,114,46,41,1,114, + 35,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 159,0,0,0,12,4,0,0,115,2,0,0,0,0,3,122, + 32,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, + 97,100,101,114,46,103,101,116,95,102,105,108,101,110,97,109, + 101,78,41,14,114,107,0,0,0,114,106,0,0,0,114,108, + 0,0,0,114,109,0,0,0,114,186,0,0,0,114,215,0, + 0,0,114,217,0,0,0,114,187,0,0,0,114,192,0,0, + 0,114,161,0,0,0,114,188,0,0,0,114,202,0,0,0, + 114,118,0,0,0,114,159,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,226, + 0,0,0,221,3,0,0,115,18,0,0,0,12,8,8,4, + 8,4,8,3,8,8,8,6,8,6,8,4,8,4,114,226, + 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,64,0,0,0,115,96,0,0,0,101,0,90, + 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, + 4,100,4,100,5,132,0,90,5,100,6,100,7,132,0,90, + 6,100,8,100,9,132,0,90,7,100,10,100,11,132,0,90, + 8,100,12,100,13,132,0,90,9,100,14,100,15,132,0,90, + 10,100,16,100,17,132,0,90,11,100,18,100,19,132,0,90, + 12,100,20,100,21,132,0,90,13,100,22,83,0,41,23,218, + 14,95,78,97,109,101,115,112,97,99,101,80,97,116,104,97, + 38,1,0,0,82,101,112,114,101,115,101,110,116,115,32,97, + 32,110,97,109,101,115,112,97,99,101,32,112,97,99,107,97, + 103,101,39,115,32,112,97,116,104,46,32,32,73,116,32,117, + 115,101,115,32,116,104,101,32,109,111,100,117,108,101,32,110, + 97,109,101,10,32,32,32,32,116,111,32,102,105,110,100,32, + 105,116,115,32,112,97,114,101,110,116,32,109,111,100,117,108, + 101,44,32,97,110,100,32,102,114,111,109,32,116,104,101,114, + 101,32,105,116,32,108,111,111,107,115,32,117,112,32,116,104, + 101,32,112,97,114,101,110,116,39,115,10,32,32,32,32,95, + 95,112,97,116,104,95,95,46,32,32,87,104,101,110,32,116, + 104,105,115,32,99,104,97,110,103,101,115,44,32,116,104,101, + 32,109,111,100,117,108,101,39,115,32,111,119,110,32,112,97, + 116,104,32,105,115,32,114,101,99,111,109,112,117,116,101,100, + 44,10,32,32,32,32,117,115,105,110,103,32,112,97,116,104, + 95,102,105,110,100,101,114,46,32,32,70,111,114,32,116,111, + 112,45,108,101,118,101,108,32,109,111,100,117,108,101,115,44, + 32,116,104,101,32,112,97,114,101,110,116,32,109,111,100,117, + 108,101,39,115,32,112,97,116,104,10,32,32,32,32,105,115, + 32,115,121,115,46,112,97,116,104,46,99,4,0,0,0,0, + 0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115, + 36,0,0,0,124,1,124,0,95,0,124,2,124,0,95,1, + 116,2,124,0,160,3,161,0,131,1,124,0,95,4,124,3, + 124,0,95,5,100,0,83,0,41,1,78,41,6,218,5,95, + 110,97,109,101,218,5,95,112,97,116,104,114,95,0,0,0, + 218,16,95,103,101,116,95,112,97,114,101,110,116,95,112,97, + 116,104,218,17,95,108,97,115,116,95,112,97,114,101,110,116, + 95,112,97,116,104,218,12,95,112,97,116,104,95,102,105,110, + 100,101,114,41,4,114,102,0,0,0,114,100,0,0,0,114, + 35,0,0,0,218,11,112,97,116,104,95,102,105,110,100,101, + 114,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,186,0,0,0,25,4,0,0,115,8,0,0,0,0,1, + 6,1,6,1,14,1,122,23,95,78,97,109,101,115,112,97, + 99,101,80,97,116,104,46,95,95,105,110,105,116,95,95,99, + 1,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, + 67,0,0,0,115,38,0,0,0,124,0,106,0,160,1,100, + 1,161,1,92,3,125,1,125,2,125,3,124,2,100,2,107, + 2,114,30,100,3,83,0,124,1,100,4,102,2,83,0,41, + 5,122,62,82,101,116,117,114,110,115,32,97,32,116,117,112, + 108,101,32,111,102,32,40,112,97,114,101,110,116,45,109,111, + 100,117,108,101,45,110,97,109,101,44,32,112,97,114,101,110, + 116,45,112,97,116,104,45,97,116,116,114,45,110,97,109,101, + 41,114,59,0,0,0,114,30,0,0,0,41,2,114,6,0, + 0,0,114,35,0,0,0,90,8,95,95,112,97,116,104,95, + 95,41,2,114,233,0,0,0,114,32,0,0,0,41,4,114, + 102,0,0,0,114,224,0,0,0,218,3,100,111,116,90,2, + 109,101,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,23,95,102,105,110,100,95,112,97,114,101,110,116,95, + 112,97,116,104,95,110,97,109,101,115,31,4,0,0,115,8, + 0,0,0,0,2,18,1,8,2,4,3,122,38,95,78,97, + 109,101,115,112,97,99,101,80,97,116,104,46,95,102,105,110, + 100,95,112,97,114,101,110,116,95,112,97,116,104,95,110,97, + 109,101,115,99,1,0,0,0,0,0,0,0,3,0,0,0, + 3,0,0,0,67,0,0,0,115,28,0,0,0,124,0,160, + 0,161,0,92,2,125,1,125,2,116,1,116,2,106,3,124, + 1,25,0,124,2,131,2,83,0,41,1,78,41,4,114,240, + 0,0,0,114,112,0,0,0,114,6,0,0,0,218,7,109, + 111,100,117,108,101,115,41,3,114,102,0,0,0,90,18,112, + 97,114,101,110,116,95,109,111,100,117,108,101,95,110,97,109, + 101,90,14,112,97,116,104,95,97,116,116,114,95,110,97,109, + 101,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,235,0,0,0,41,4,0,0,115,4,0,0,0,0,1, + 12,1,122,31,95,78,97,109,101,115,112,97,99,101,80,97, + 116,104,46,95,103,101,116,95,112,97,114,101,110,116,95,112, + 97,116,104,99,1,0,0,0,0,0,0,0,3,0,0,0, + 4,0,0,0,67,0,0,0,115,80,0,0,0,116,0,124, + 0,160,1,161,0,131,1,125,1,124,1,124,0,106,2,107, + 3,114,74,124,0,160,3,124,0,106,4,124,1,161,2,125, + 2,124,2,100,0,107,9,114,68,124,2,106,5,100,0,107, + 8,114,68,124,2,106,6,114,68,124,2,106,6,124,0,95, + 7,124,1,124,0,95,2,124,0,106,7,83,0,41,1,78, + 41,8,114,95,0,0,0,114,235,0,0,0,114,236,0,0, + 0,114,237,0,0,0,114,233,0,0,0,114,122,0,0,0, + 114,158,0,0,0,114,234,0,0,0,41,3,114,102,0,0, + 0,90,11,112,97,114,101,110,116,95,112,97,116,104,114,166, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,12,95,114,101,99,97,108,99,117,108,97,116,101, + 45,4,0,0,115,16,0,0,0,0,2,12,1,10,1,14, + 3,18,1,6,1,8,1,6,1,122,27,95,78,97,109,101, + 115,112,97,99,101,80,97,116,104,46,95,114,101,99,97,108, + 99,117,108,97,116,101,99,1,0,0,0,0,0,0,0,1, + 0,0,0,3,0,0,0,67,0,0,0,115,12,0,0,0, + 116,0,124,0,160,1,161,0,131,1,83,0,41,1,78,41, + 2,218,4,105,116,101,114,114,242,0,0,0,41,1,114,102, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,8,95,95,105,116,101,114,95,95,58,4,0,0, + 115,2,0,0,0,0,1,122,23,95,78,97,109,101,115,112, + 97,99,101,80,97,116,104,46,95,95,105,116,101,114,95,95, + 99,3,0,0,0,0,0,0,0,3,0,0,0,3,0,0, + 0,67,0,0,0,115,14,0,0,0,124,2,124,0,106,0, + 124,1,60,0,100,0,83,0,41,1,78,41,1,114,234,0, + 0,0,41,3,114,102,0,0,0,218,5,105,110,100,101,120, + 114,35,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,218,11,95,95,115,101,116,105,116,101,109,95, + 95,61,4,0,0,115,2,0,0,0,0,1,122,26,95,78, + 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,115, + 101,116,105,116,101,109,95,95,99,1,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,67,0,0,0,115,12,0, + 0,0,116,0,124,0,160,1,161,0,131,1,83,0,41,1, + 78,41,2,114,31,0,0,0,114,242,0,0,0,41,1,114, + 102,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,218,7,95,95,108,101,110,95,95,64,4,0,0, + 115,2,0,0,0,0,1,122,22,95,78,97,109,101,115,112, + 97,99,101,80,97,116,104,46,95,95,108,101,110,95,95,99, + 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,115,12,0,0,0,100,1,160,0,124,0,106, + 1,161,1,83,0,41,2,78,122,20,95,78,97,109,101,115, + 112,97,99,101,80,97,116,104,40,123,33,114,125,41,41,2, + 114,48,0,0,0,114,234,0,0,0,41,1,114,102,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,8,95,95,114,101,112,114,95,95,67,4,0,0,115,2, + 0,0,0,0,1,122,23,95,78,97,109,101,115,112,97,99, + 101,80,97,116,104,46,95,95,114,101,112,114,95,95,99,2, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,12,0,0,0,124,1,124,0,160,0,161,0, + 107,6,83,0,41,1,78,41,1,114,242,0,0,0,41,2, + 114,102,0,0,0,218,4,105,116,101,109,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,218,12,95,95,99,111, + 110,116,97,105,110,115,95,95,70,4,0,0,115,2,0,0, + 0,0,1,122,27,95,78,97,109,101,115,112,97,99,101,80, + 97,116,104,46,95,95,99,111,110,116,97,105,110,115,95,95, + 99,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0, + 0,67,0,0,0,115,16,0,0,0,124,0,106,0,160,1, + 124,1,161,1,1,0,100,0,83,0,41,1,78,41,2,114, + 234,0,0,0,114,165,0,0,0,41,2,114,102,0,0,0, + 114,249,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,165,0,0,0,73,4,0,0,115,2,0, + 0,0,0,1,122,21,95,78,97,109,101,115,112,97,99,101, + 80,97,116,104,46,97,112,112,101,110,100,78,41,14,114,107, + 0,0,0,114,106,0,0,0,114,108,0,0,0,114,109,0, + 0,0,114,186,0,0,0,114,240,0,0,0,114,235,0,0, + 0,114,242,0,0,0,114,244,0,0,0,114,246,0,0,0, + 114,247,0,0,0,114,248,0,0,0,114,250,0,0,0,114, + 165,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,232,0,0,0,18,4,0, + 0,115,20,0,0,0,12,7,8,6,8,10,8,4,8,13, + 8,3,8,3,8,3,8,3,8,3,114,232,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, + 64,0,0,0,115,80,0,0,0,101,0,90,1,100,0,90, + 2,100,1,100,2,132,0,90,3,101,4,100,3,100,4,132, + 0,131,1,90,5,100,5,100,6,132,0,90,6,100,7,100, + 8,132,0,90,7,100,9,100,10,132,0,90,8,100,11,100, + 12,132,0,90,9,100,13,100,14,132,0,90,10,100,15,100, + 16,132,0,90,11,100,17,83,0,41,18,218,16,95,78,97, + 109,101,115,112,97,99,101,76,111,97,100,101,114,99,4,0, + 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, + 0,0,115,18,0,0,0,116,0,124,1,124,2,124,3,131, + 3,124,0,95,1,100,0,83,0,41,1,78,41,2,114,232, + 0,0,0,114,234,0,0,0,41,4,114,102,0,0,0,114, + 100,0,0,0,114,35,0,0,0,114,238,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,186,0, + 0,0,79,4,0,0,115,2,0,0,0,0,1,122,25,95, + 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, + 95,95,105,110,105,116,95,95,99,2,0,0,0,0,0,0, + 0,2,0,0,0,3,0,0,0,67,0,0,0,115,12,0, + 0,0,100,1,160,0,124,1,106,1,161,1,83,0,41,2, + 122,115,82,101,116,117,114,110,32,114,101,112,114,32,102,111, + 114,32,116,104,101,32,109,111,100,117,108,101,46,10,10,32, + 32,32,32,32,32,32,32,84,104,101,32,109,101,116,104,111, + 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, + 32,32,84,104,101,32,105,109,112,111,114,116,32,109,97,99, + 104,105,110,101,114,121,32,100,111,101,115,32,116,104,101,32, + 106,111,98,32,105,116,115,101,108,102,46,10,10,32,32,32, + 32,32,32,32,32,122,25,60,109,111,100,117,108,101,32,123, + 33,114,125,32,40,110,97,109,101,115,112,97,99,101,41,62, + 41,2,114,48,0,0,0,114,107,0,0,0,41,2,114,172, + 0,0,0,114,191,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,11,109,111,100,117,108,101,95, + 114,101,112,114,82,4,0,0,115,2,0,0,0,0,7,122, + 28,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, + 114,46,109,111,100,117,108,101,95,114,101,112,114,99,2,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,115,4,0,0,0,100,1,83,0,41,2,78,84,114, + 2,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 161,0,0,0,91,4,0,0,115,2,0,0,0,0,1,122, + 27,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, + 114,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,83,0,41,2,78,114,30,0, + 0,0,114,2,0,0,0,41,2,114,102,0,0,0,114,121, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,202,0,0,0,94,4,0,0,115,2,0,0,0, + 0,1,122,27,95,78,97,109,101,115,112,97,99,101,76,111, + 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,6,0,0,0, + 67,0,0,0,115,16,0,0,0,116,0,100,1,100,2,100, + 3,100,4,100,5,141,4,83,0,41,6,78,114,30,0,0, + 0,122,8,60,115,116,114,105,110,103,62,114,190,0,0,0, + 84,41,1,114,204,0,0,0,41,1,114,205,0,0,0,41, + 2,114,102,0,0,0,114,121,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,188,0,0,0,97, + 4,0,0,115,2,0,0,0,0,1,122,25,95,78,97,109, + 101,115,112,97,99,101,76,111,97,100,101,114,46,103,101,116, + 95,99,111,100,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, + 1,83,0,41,2,122,42,85,115,101,32,100,101,102,97,117, + 108,116,32,115,101,109,97,110,116,105,99,115,32,102,111,114, + 32,109,111,100,117,108,101,32,99,114,101,97,116,105,111,110, + 46,78,114,2,0,0,0,41,2,114,102,0,0,0,114,166, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,187,0,0,0,100,4,0,0,115,0,0,0,0, + 122,30,95,78,97,109,101,115,112,97,99,101,76,111,97,100, + 101,114,46,99,114,101,97,116,101,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,4,0,0,0,100,0,83,0,41,1, + 78,114,2,0,0,0,41,2,114,102,0,0,0,114,191,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,192,0,0,0,103,4,0,0,115,2,0,0,0,0, + 1,122,28,95,78,97,109,101,115,112,97,99,101,76,111,97, + 100,101,114,46,101,120,101,99,95,109,111,100,117,108,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, + 67,0,0,0,115,26,0,0,0,116,0,160,1,100,1,124, + 0,106,2,161,2,1,0,116,0,160,3,124,0,124,1,161, + 2,83,0,41,2,122,98,76,111,97,100,32,97,32,110,97, + 109,101,115,112,97,99,101,32,109,111,100,117,108,101,46,10, + 10,32,32,32,32,32,32,32,32,84,104,105,115,32,109,101, + 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, + 101,100,46,32,32,85,115,101,32,101,120,101,99,95,109,111, + 100,117,108,101,40,41,32,105,110,115,116,101,97,100,46,10, + 10,32,32,32,32,32,32,32,32,122,38,110,97,109,101,115, + 112,97,99,101,32,109,111,100,117,108,101,32,108,111,97,100, + 101,100,32,119,105,116,104,32,112,97,116,104,32,123,33,114, + 125,41,4,114,116,0,0,0,114,130,0,0,0,114,234,0, + 0,0,114,193,0,0,0,41,2,114,102,0,0,0,114,121, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,194,0,0,0,106,4,0,0,115,6,0,0,0, + 0,7,6,1,8,1,122,28,95,78,97,109,101,115,112,97, + 99,101,76,111,97,100,101,114,46,108,111,97,100,95,109,111, + 100,117,108,101,78,41,12,114,107,0,0,0,114,106,0,0, + 0,114,108,0,0,0,114,186,0,0,0,114,184,0,0,0, + 114,252,0,0,0,114,161,0,0,0,114,202,0,0,0,114, + 188,0,0,0,114,187,0,0,0,114,192,0,0,0,114,194, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,114,251,0,0,0,78,4,0,0, + 115,16,0,0,0,8,1,8,3,12,9,8,3,8,3,8, + 3,8,3,8,3,114,251,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,90,1,100,0,90,2,100,1,90,3, + 101,4,100,2,100,3,132,0,131,1,90,5,101,4,100,4, + 100,5,132,0,131,1,90,6,101,4,100,6,100,7,132,0, + 131,1,90,7,101,4,100,8,100,9,132,0,131,1,90,8, + 101,4,100,17,100,11,100,12,132,1,131,1,90,9,101,4, + 100,18,100,13,100,14,132,1,131,1,90,10,101,4,100,19, + 100,15,100,16,132,1,131,1,90,11,100,10,83,0,41,20, + 218,10,80,97,116,104,70,105,110,100,101,114,122,62,77,101, + 116,97,32,112,97,116,104,32,102,105,110,100,101,114,32,102, + 111,114,32,115,121,115,46,112,97,116,104,32,97,110,100,32, + 112,97,99,107,97,103,101,32,95,95,112,97,116,104,95,95, + 32,97,116,116,114,105,98,117,116,101,115,46,99,1,0,0, + 0,0,0,0,0,2,0,0,0,4,0,0,0,67,0,0, + 0,115,42,0,0,0,120,36,116,0,106,1,160,2,161,0, + 68,0,93,22,125,1,116,3,124,1,100,1,131,2,114,12, + 124,1,160,4,161,0,1,0,113,12,87,0,100,2,83,0, + 41,3,122,125,67,97,108,108,32,116,104,101,32,105,110,118, + 97,108,105,100,97,116,101,95,99,97,99,104,101,115,40,41, + 32,109,101,116,104,111,100,32,111,110,32,97,108,108,32,112, + 97,116,104,32,101,110,116,114,121,32,102,105,110,100,101,114, + 115,10,32,32,32,32,32,32,32,32,115,116,111,114,101,100, + 32,105,110,32,115,121,115,46,112,97,116,104,95,105,109,112, + 111,114,116,101,114,95,99,97,99,104,101,115,32,40,119,104, + 101,114,101,32,105,109,112,108,101,109,101,110,116,101,100,41, + 46,218,17,105,110,118,97,108,105,100,97,116,101,95,99,97, + 99,104,101,115,78,41,5,114,6,0,0,0,218,19,112,97, + 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, + 101,218,6,118,97,108,117,101,115,114,110,0,0,0,114,254, + 0,0,0,41,2,114,172,0,0,0,218,6,102,105,110,100, + 101,114,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,254,0,0,0,124,4,0,0,115,6,0,0,0,0, + 4,16,1,10,1,122,28,80,97,116,104,70,105,110,100,101, + 114,46,105,110,118,97,108,105,100,97,116,101,95,99,97,99, + 104,101,115,99,2,0,0,0,0,0,0,0,3,0,0,0, + 12,0,0,0,67,0,0,0,115,84,0,0,0,116,0,106, + 1,100,1,107,9,114,28,116,0,106,1,115,28,116,2,160, + 3,100,2,116,4,161,2,1,0,120,50,116,0,106,1,68, + 0,93,36,125,2,121,8,124,2,124,1,131,1,83,0,4, + 0,116,5,107,10,114,70,1,0,1,0,1,0,119,36,89, + 0,113,36,88,0,113,36,87,0,100,1,83,0,100,1,83, + 0,41,3,122,46,83,101,97,114,99,104,32,115,121,115,46, + 112,97,116,104,95,104,111,111,107,115,32,102,111,114,32,97, + 32,102,105,110,100,101,114,32,102,111,114,32,39,112,97,116, + 104,39,46,78,122,23,115,121,115,46,112,97,116,104,95,104, + 111,111,107,115,32,105,115,32,101,109,112,116,121,41,6,114, + 6,0,0,0,218,10,112,97,116,104,95,104,111,111,107,115, + 114,61,0,0,0,114,62,0,0,0,114,120,0,0,0,114, + 101,0,0,0,41,3,114,172,0,0,0,114,35,0,0,0, + 90,4,104,111,111,107,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,11,95,112,97,116,104,95,104,111,111, + 107,115,132,4,0,0,115,16,0,0,0,0,3,16,1,12, + 1,12,1,2,1,8,1,14,1,12,2,122,22,80,97,116, + 104,70,105,110,100,101,114,46,95,112,97,116,104,95,104,111, + 111,107,115,99,2,0,0,0,0,0,0,0,3,0,0,0, + 19,0,0,0,67,0,0,0,115,102,0,0,0,124,1,100, + 1,107,2,114,42,121,12,116,0,160,1,161,0,125,1,87, + 0,110,20,4,0,116,2,107,10,114,40,1,0,1,0,1, + 0,100,2,83,0,88,0,121,14,116,3,106,4,124,1,25, + 0,125,2,87,0,110,40,4,0,116,5,107,10,114,96,1, + 0,1,0,1,0,124,0,160,6,124,1,161,1,125,2,124, + 2,116,3,106,4,124,1,60,0,89,0,110,2,88,0,124, + 2,83,0,41,3,122,210,71,101,116,32,116,104,101,32,102, + 105,110,100,101,114,32,102,111,114,32,116,104,101,32,112,97, + 116,104,32,101,110,116,114,121,32,102,114,111,109,32,115,121, + 115,46,112,97,116,104,95,105,109,112,111,114,116,101,114,95, + 99,97,99,104,101,46,10,10,32,32,32,32,32,32,32,32, + 73,102,32,116,104,101,32,112,97,116,104,32,101,110,116,114, + 121,32,105,115,32,110,111,116,32,105,110,32,116,104,101,32, + 99,97,99,104,101,44,32,102,105,110,100,32,116,104,101,32, + 97,112,112,114,111,112,114,105,97,116,101,32,102,105,110,100, + 101,114,10,32,32,32,32,32,32,32,32,97,110,100,32,99, + 97,99,104,101,32,105,116,46,32,73,102,32,110,111,32,102, + 105,110,100,101,114,32,105,115,32,97,118,97,105,108,97,98, + 108,101,44,32,115,116,111,114,101,32,78,111,110,101,46,10, + 10,32,32,32,32,32,32,32,32,114,30,0,0,0,78,41, + 7,114,1,0,0,0,114,45,0,0,0,218,17,70,105,108, + 101,78,111,116,70,111,117,110,100,69,114,114,111,114,114,6, + 0,0,0,114,255,0,0,0,218,8,75,101,121,69,114,114, + 111,114,114,3,1,0,0,41,3,114,172,0,0,0,114,35, + 0,0,0,114,1,1,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,20,95,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,145,4,0, + 0,115,22,0,0,0,0,8,8,1,2,1,12,1,14,3, + 6,1,2,1,14,1,14,1,10,1,16,1,122,31,80,97, + 116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,99,3,0, + 0,0,0,0,0,0,6,0,0,0,4,0,0,0,67,0, + 0,0,115,82,0,0,0,116,0,124,2,100,1,131,2,114, + 26,124,2,160,1,124,1,161,1,92,2,125,3,125,4,110, + 14,124,2,160,2,124,1,161,1,125,3,103,0,125,4,124, + 3,100,0,107,9,114,60,116,3,160,4,124,1,124,3,161, + 2,83,0,116,3,160,5,124,1,100,0,161,2,125,5,124, + 4,124,5,95,6,124,5,83,0,41,2,78,114,119,0,0, + 0,41,7,114,110,0,0,0,114,119,0,0,0,114,183,0, + 0,0,114,116,0,0,0,114,180,0,0,0,114,162,0,0, + 0,114,158,0,0,0,41,6,114,172,0,0,0,114,121,0, + 0,0,114,1,1,0,0,114,122,0,0,0,114,123,0,0, + 0,114,166,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,16,95,108,101,103,97,99,121,95,103, + 101,116,95,115,112,101,99,167,4,0,0,115,18,0,0,0, + 0,4,10,1,16,2,10,1,4,1,8,1,12,1,12,1, + 6,1,122,27,80,97,116,104,70,105,110,100,101,114,46,95, + 108,101,103,97,99,121,95,103,101,116,95,115,112,101,99,78, + 99,4,0,0,0,0,0,0,0,9,0,0,0,5,0,0, + 0,67,0,0,0,115,170,0,0,0,103,0,125,4,120,160, + 124,2,68,0,93,130,125,5,116,0,124,5,116,1,116,2, + 102,2,131,2,115,30,113,10,124,0,160,3,124,5,161,1, + 125,6,124,6,100,1,107,9,114,10,116,4,124,6,100,2, + 131,2,114,72,124,6,160,5,124,1,124,3,161,2,125,7, + 110,12,124,0,160,6,124,1,124,6,161,2,125,7,124,7, + 100,1,107,8,114,94,113,10,124,7,106,7,100,1,107,9, + 114,108,124,7,83,0,124,7,106,8,125,8,124,8,100,1, + 107,8,114,130,116,9,100,3,131,1,130,1,124,4,160,10, + 124,8,161,1,1,0,113,10,87,0,116,11,160,12,124,1, + 100,1,161,2,125,7,124,4,124,7,95,8,124,7,83,0, + 100,1,83,0,41,4,122,63,70,105,110,100,32,116,104,101, + 32,108,111,97,100,101,114,32,111,114,32,110,97,109,101,115, + 112,97,99,101,95,112,97,116,104,32,102,111,114,32,116,104, + 105,115,32,109,111,100,117,108,101,47,112,97,99,107,97,103, + 101,32,110,97,109,101,46,78,114,182,0,0,0,122,19,115, + 112,101,99,32,109,105,115,115,105,110,103,32,108,111,97,100, + 101,114,41,13,114,141,0,0,0,114,71,0,0,0,218,5, + 98,121,116,101,115,114,6,1,0,0,114,110,0,0,0,114, + 182,0,0,0,114,7,1,0,0,114,122,0,0,0,114,158, + 0,0,0,114,101,0,0,0,114,147,0,0,0,114,116,0, + 0,0,114,162,0,0,0,41,9,114,172,0,0,0,114,121, + 0,0,0,114,35,0,0,0,114,181,0,0,0,218,14,110, + 97,109,101,115,112,97,99,101,95,112,97,116,104,90,5,101, + 110,116,114,121,114,1,1,0,0,114,166,0,0,0,114,123, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,9,95,103,101,116,95,115,112,101,99,182,4,0, + 0,115,40,0,0,0,0,5,4,1,10,1,14,1,2,1, + 10,1,8,1,10,1,14,2,12,1,8,1,2,1,10,1, + 4,1,6,1,8,1,8,5,14,2,12,1,6,1,122,20, + 80,97,116,104,70,105,110,100,101,114,46,95,103,101,116,95, + 115,112,101,99,99,4,0,0,0,0,0,0,0,6,0,0, + 0,5,0,0,0,67,0,0,0,115,100,0,0,0,124,2, + 100,1,107,8,114,14,116,0,106,1,125,2,124,0,160,2, + 124,1,124,2,124,3,161,3,125,4,124,4,100,1,107,8, + 114,40,100,1,83,0,124,4,106,3,100,1,107,8,114,92, + 124,4,106,4,125,5,124,5,114,86,100,2,124,4,95,5, + 116,6,124,1,124,5,124,0,106,2,131,3,124,4,95,4, + 124,4,83,0,100,1,83,0,110,4,124,4,83,0,100,1, + 83,0,41,3,122,141,84,114,121,32,116,111,32,102,105,110, + 100,32,97,32,115,112,101,99,32,102,111,114,32,39,102,117, + 108,108,110,97,109,101,39,32,111,110,32,115,121,115,46,112, + 97,116,104,32,111,114,32,39,112,97,116,104,39,46,10,10, + 32,32,32,32,32,32,32,32,84,104,101,32,115,101,97,114, + 99,104,32,105,115,32,98,97,115,101,100,32,111,110,32,115, + 121,115,46,112,97,116,104,95,104,111,111,107,115,32,97,110, + 100,32,115,121,115,46,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,46,10,32,32,32,32,32, + 32,32,32,78,90,9,110,97,109,101,115,112,97,99,101,41, + 7,114,6,0,0,0,114,35,0,0,0,114,10,1,0,0, + 114,122,0,0,0,114,158,0,0,0,114,160,0,0,0,114, + 232,0,0,0,41,6,114,172,0,0,0,114,121,0,0,0, + 114,35,0,0,0,114,181,0,0,0,114,166,0,0,0,114, + 9,1,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,182,0,0,0,214,4,0,0,115,26,0,0, + 0,0,6,8,1,6,1,14,1,8,1,4,1,10,1,6, + 1,4,3,6,1,16,1,4,2,6,2,122,20,80,97,116, + 104,70,105,110,100,101,114,46,102,105,110,100,95,115,112,101, + 99,99,3,0,0,0,0,0,0,0,4,0,0,0,4,0, + 0,0,67,0,0,0,115,30,0,0,0,124,0,160,0,124, + 1,124,2,161,2,125,3,124,3,100,1,107,8,114,24,100, + 1,83,0,124,3,106,1,83,0,41,2,122,170,102,105,110, + 100,32,116,104,101,32,109,111,100,117,108,101,32,111,110,32, + 115,121,115,46,112,97,116,104,32,111,114,32,39,112,97,116, + 104,39,32,98,97,115,101,100,32,111,110,32,115,121,115,46, + 112,97,116,104,95,104,111,111,107,115,32,97,110,100,10,32, + 32,32,32,32,32,32,32,115,121,115,46,112,97,116,104,95, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,46,10, + 10,32,32,32,32,32,32,32,32,84,104,105,115,32,109,101, + 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, + 101,100,46,32,32,85,115,101,32,102,105,110,100,95,115,112, + 101,99,40,41,32,105,110,115,116,101,97,100,46,10,10,32, + 32,32,32,32,32,32,32,78,41,2,114,182,0,0,0,114, + 122,0,0,0,41,4,114,172,0,0,0,114,121,0,0,0, + 114,35,0,0,0,114,166,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,183,0,0,0,238,4, + 0,0,115,8,0,0,0,0,8,12,1,8,1,4,1,122, + 22,80,97,116,104,70,105,110,100,101,114,46,102,105,110,100, + 95,109,111,100,117,108,101,41,1,78,41,2,78,78,41,1, + 78,41,12,114,107,0,0,0,114,106,0,0,0,114,108,0, + 0,0,114,109,0,0,0,114,184,0,0,0,114,254,0,0, + 0,114,3,1,0,0,114,6,1,0,0,114,7,1,0,0, + 114,10,1,0,0,114,182,0,0,0,114,183,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,253,0,0,0,120,4,0,0,115,20,0,0, + 0,12,4,12,8,12,13,12,22,12,15,2,1,12,31,2, + 1,12,23,2,1,114,253,0,0,0,99,0,0,0,0,0, + 0,0,0,0,0,0,0,3,0,0,0,64,0,0,0,115, + 90,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, + 100,2,100,3,132,0,90,4,100,4,100,5,132,0,90,5, + 101,6,90,7,100,6,100,7,132,0,90,8,100,8,100,9, + 132,0,90,9,100,19,100,11,100,12,132,1,90,10,100,13, + 100,14,132,0,90,11,101,12,100,15,100,16,132,0,131,1, + 90,13,100,17,100,18,132,0,90,14,100,10,83,0,41,20, + 218,10,70,105,108,101,70,105,110,100,101,114,122,172,70,105, + 108,101,45,98,97,115,101,100,32,102,105,110,100,101,114,46, + 10,10,32,32,32,32,73,110,116,101,114,97,99,116,105,111, + 110,115,32,119,105,116,104,32,116,104,101,32,102,105,108,101, + 32,115,121,115,116,101,109,32,97,114,101,32,99,97,99,104, + 101,100,32,102,111,114,32,112,101,114,102,111,114,109,97,110, + 99,101,44,32,98,101,105,110,103,10,32,32,32,32,114,101, + 102,114,101,115,104,101,100,32,119,104,101,110,32,116,104,101, + 32,100,105,114,101,99,116,111,114,121,32,116,104,101,32,102, + 105,110,100,101,114,32,105,115,32,104,97,110,100,108,105,110, + 103,32,104,97,115,32,98,101,101,110,32,109,111,100,105,102, + 105,101,100,46,10,10,32,32,32,32,99,2,0,0,0,0, + 0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,115, + 88,0,0,0,103,0,125,3,120,40,124,2,68,0,93,32, + 92,2,137,0,125,4,124,3,160,0,135,0,102,1,100,1, + 100,2,132,8,124,4,68,0,131,1,161,1,1,0,113,10, + 87,0,124,3,124,0,95,1,124,1,112,58,100,3,124,0, + 95,2,100,4,124,0,95,3,116,4,131,0,124,0,95,5, + 116,4,131,0,124,0,95,6,100,5,83,0,41,6,122,154, + 73,110,105,116,105,97,108,105,122,101,32,119,105,116,104,32, + 116,104,101,32,112,97,116,104,32,116,111,32,115,101,97,114, + 99,104,32,111,110,32,97,110,100,32,97,32,118,97,114,105, + 97,98,108,101,32,110,117,109,98,101,114,32,111,102,10,32, + 32,32,32,32,32,32,32,50,45,116,117,112,108,101,115,32, + 99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,108, + 111,97,100,101,114,32,97,110,100,32,116,104,101,32,102,105, + 108,101,32,115,117,102,102,105,120,101,115,32,116,104,101,32, + 108,111,97,100,101,114,10,32,32,32,32,32,32,32,32,114, + 101,99,111,103,110,105,122,101,115,46,99,1,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,51,0,0,0,115, + 22,0,0,0,124,0,93,14,125,1,124,1,136,0,102,2, + 86,0,1,0,113,2,100,0,83,0,41,1,78,114,2,0, + 0,0,41,2,114,22,0,0,0,114,227,0,0,0,41,1, + 114,122,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 229,0,0,0,11,5,0,0,115,2,0,0,0,4,0,122, + 38,70,105,108,101,70,105,110,100,101,114,46,95,95,105,110, + 105,116,95,95,46,60,108,111,99,97,108,115,62,46,60,103, + 101,110,101,120,112,114,62,114,59,0,0,0,114,89,0,0, + 0,78,41,7,114,147,0,0,0,218,8,95,108,111,97,100, + 101,114,115,114,35,0,0,0,218,11,95,112,97,116,104,95, + 109,116,105,109,101,218,3,115,101,116,218,11,95,112,97,116, + 104,95,99,97,99,104,101,218,19,95,114,101,108,97,120,101, + 100,95,112,97,116,104,95,99,97,99,104,101,41,5,114,102, + 0,0,0,114,35,0,0,0,218,14,108,111,97,100,101,114, + 95,100,101,116,97,105,108,115,90,7,108,111,97,100,101,114, + 115,114,168,0,0,0,114,2,0,0,0,41,1,114,122,0, + 0,0,114,4,0,0,0,114,186,0,0,0,5,5,0,0, + 115,16,0,0,0,0,4,4,1,14,1,28,1,6,2,10, + 1,6,1,8,1,122,19,70,105,108,101,70,105,110,100,101, + 114,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, + 0,0,0,1,0,0,0,2,0,0,0,67,0,0,0,115, + 10,0,0,0,100,1,124,0,95,0,100,2,83,0,41,3, + 122,31,73,110,118,97,108,105,100,97,116,101,32,116,104,101, + 32,100,105,114,101,99,116,111,114,121,32,109,116,105,109,101, + 46,114,89,0,0,0,78,41,1,114,13,1,0,0,41,1, + 114,102,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,254,0,0,0,19,5,0,0,115,2,0, + 0,0,0,2,122,28,70,105,108,101,70,105,110,100,101,114, 46,105,110,118,97,108,105,100,97,116,101,95,99,97,99,104, - 101,115,99,2,0,0,0,0,0,0,0,3,0,0,0,12, - 0,0,0,67,0,0,0,115,84,0,0,0,116,0,106,1, - 100,1,107,9,114,28,116,0,106,1,115,28,116,2,160,3, - 100,2,116,4,161,2,1,0,120,50,116,0,106,1,68,0, - 93,36,125,2,121,8,124,2,124,1,131,1,83,0,4,0, - 116,5,107,10,114,70,1,0,1,0,1,0,119,36,89,0, - 113,36,88,0,113,36,87,0,100,1,83,0,100,1,83,0, - 41,3,122,46,83,101,97,114,99,104,32,115,121,115,46,112, - 97,116,104,95,104,111,111,107,115,32,102,111,114,32,97,32, - 102,105,110,100,101,114,32,102,111,114,32,39,112,97,116,104, - 39,46,78,122,23,115,121,115,46,112,97,116,104,95,104,111, - 111,107,115,32,105,115,32,101,109,112,116,121,41,6,114,8, - 0,0,0,218,10,112,97,116,104,95,104,111,111,107,115,114, - 63,0,0,0,114,64,0,0,0,114,122,0,0,0,114,103, - 0,0,0,41,3,114,174,0,0,0,114,37,0,0,0,90, - 4,104,111,111,107,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,11,95,112,97,116,104,95,104,111,111,107, - 115,132,4,0,0,115,16,0,0,0,0,3,16,1,12,1, - 12,1,2,1,8,1,14,1,12,2,122,22,80,97,116,104, - 70,105,110,100,101,114,46,95,112,97,116,104,95,104,111,111, - 107,115,99,2,0,0,0,0,0,0,0,3,0,0,0,19, - 0,0,0,67,0,0,0,115,102,0,0,0,124,1,100,1, - 107,2,114,42,121,12,116,0,160,1,161,0,125,1,87,0, - 110,20,4,0,116,2,107,10,114,40,1,0,1,0,1,0, - 100,2,83,0,88,0,121,14,116,3,106,4,124,1,25,0, - 125,2,87,0,110,40,4,0,116,5,107,10,114,96,1,0, - 1,0,1,0,124,0,160,6,124,1,161,1,125,2,124,2, - 116,3,106,4,124,1,60,0,89,0,110,2,88,0,124,2, - 83,0,41,3,122,210,71,101,116,32,116,104,101,32,102,105, - 110,100,101,114,32,102,111,114,32,116,104,101,32,112,97,116, - 104,32,101,110,116,114,121,32,102,114,111,109,32,115,121,115, - 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, - 97,99,104,101,46,10,10,32,32,32,32,32,32,32,32,73, - 102,32,116,104,101,32,112,97,116,104,32,101,110,116,114,121, - 32,105,115,32,110,111,116,32,105,110,32,116,104,101,32,99, - 97,99,104,101,44,32,102,105,110,100,32,116,104,101,32,97, - 112,112,114,111,112,114,105,97,116,101,32,102,105,110,100,101, - 114,10,32,32,32,32,32,32,32,32,97,110,100,32,99,97, - 99,104,101,32,105,116,46,32,73,102,32,110,111,32,102,105, - 110,100,101,114,32,105,115,32,97,118,97,105,108,97,98,108, - 101,44,32,115,116,111,114,101,32,78,111,110,101,46,10,10, - 32,32,32,32,32,32,32,32,114,32,0,0,0,78,41,7, - 114,3,0,0,0,114,47,0,0,0,218,17,70,105,108,101, - 78,111,116,70,111,117,110,100,69,114,114,111,114,114,8,0, - 0,0,114,1,1,0,0,218,8,75,101,121,69,114,114,111, - 114,114,5,1,0,0,41,3,114,174,0,0,0,114,37,0, - 0,0,114,3,1,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,20,95,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,145,4,0,0, - 115,22,0,0,0,0,8,8,1,2,1,12,1,14,3,6, - 1,2,1,14,1,14,1,10,1,16,1,122,31,80,97,116, - 104,70,105,110,100,101,114,46,95,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,99,3,0,0, - 0,0,0,0,0,6,0,0,0,4,0,0,0,67,0,0, - 0,115,82,0,0,0,116,0,124,2,100,1,131,2,114,26, - 124,2,160,1,124,1,161,1,92,2,125,3,125,4,110,14, - 124,2,160,2,124,1,161,1,125,3,103,0,125,4,124,3, - 100,0,107,9,114,60,116,3,160,4,124,1,124,3,161,2, - 83,0,116,3,160,5,124,1,100,0,161,2,125,5,124,4, - 124,5,95,6,124,5,83,0,41,2,78,114,121,0,0,0, - 41,7,114,112,0,0,0,114,121,0,0,0,114,185,0,0, - 0,114,118,0,0,0,114,182,0,0,0,114,164,0,0,0, - 114,160,0,0,0,41,6,114,174,0,0,0,114,123,0,0, - 0,114,3,1,0,0,114,124,0,0,0,114,125,0,0,0, - 114,168,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,218,16,95,108,101,103,97,99,121,95,103,101, - 116,95,115,112,101,99,167,4,0,0,115,18,0,0,0,0, - 4,10,1,16,2,10,1,4,1,8,1,12,1,12,1,6, - 1,122,27,80,97,116,104,70,105,110,100,101,114,46,95,108, - 101,103,97,99,121,95,103,101,116,95,115,112,101,99,78,99, - 4,0,0,0,0,0,0,0,9,0,0,0,5,0,0,0, - 67,0,0,0,115,170,0,0,0,103,0,125,4,120,160,124, - 2,68,0,93,130,125,5,116,0,124,5,116,1,116,2,102, - 2,131,2,115,30,113,10,124,0,160,3,124,5,161,1,125, - 6,124,6,100,1,107,9,114,10,116,4,124,6,100,2,131, - 2,114,72,124,6,160,5,124,1,124,3,161,2,125,7,110, - 12,124,0,160,6,124,1,124,6,161,2,125,7,124,7,100, - 1,107,8,114,94,113,10,124,7,106,7,100,1,107,9,114, - 108,124,7,83,0,124,7,106,8,125,8,124,8,100,1,107, - 8,114,130,116,9,100,3,131,1,130,1,124,4,160,10,124, - 8,161,1,1,0,113,10,87,0,116,11,160,12,124,1,100, - 1,161,2,125,7,124,4,124,7,95,8,124,7,83,0,100, - 1,83,0,41,4,122,63,70,105,110,100,32,116,104,101,32, - 108,111,97,100,101,114,32,111,114,32,110,97,109,101,115,112, - 97,99,101,95,112,97,116,104,32,102,111,114,32,116,104,105, - 115,32,109,111,100,117,108,101,47,112,97,99,107,97,103,101, - 32,110,97,109,101,46,78,114,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,143,0,0,0,114,73,0,0,0,218,5,98, - 121,116,101,115,114,8,1,0,0,114,112,0,0,0,114,184, - 0,0,0,114,9,1,0,0,114,124,0,0,0,114,160,0, - 0,0,114,103,0,0,0,114,149,0,0,0,114,118,0,0, - 0,114,164,0,0,0,41,9,114,174,0,0,0,114,123,0, - 0,0,114,37,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,3,1,0,0,114,168,0,0,0,114,125,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,218,9,95,103,101,116,95,115,112,101,99,182,4,0,0, - 115,40,0,0,0,0,5,4,1,10,1,14,1,2,1,10, - 1,8,1,10,1,14,2,12,1,8,1,2,1,10,1,4, - 1,6,1,8,1,8,5,14,2,12,1,6,1,122,20,80, - 97,116,104,70,105,110,100,101,114,46,95,103,101,116,95,115, - 112,101,99,99,4,0,0,0,0,0,0,0,6,0,0,0, - 5,0,0,0,67,0,0,0,115,100,0,0,0,124,2,100, - 1,107,8,114,14,116,0,106,1,125,2,124,0,160,2,124, - 1,124,2,124,3,161,3,125,4,124,4,100,1,107,8,114, - 40,100,1,83,0,124,4,106,3,100,1,107,8,114,92,124, - 4,106,4,125,5,124,5,114,86,100,2,124,4,95,5,116, - 6,124,1,124,5,124,0,106,2,131,3,124,4,95,4,124, - 4,83,0,100,1,83,0,110,4,124,4,83,0,100,1,83, - 0,41,3,122,141,84,114,121,32,116,111,32,102,105,110,100, - 32,97,32,115,112,101,99,32,102,111,114,32,39,102,117,108, - 108,110,97,109,101,39,32,111,110,32,115,121,115,46,112,97, - 116,104,32,111,114,32,39,112,97,116,104,39,46,10,10,32, - 32,32,32,32,32,32,32,84,104,101,32,115,101,97,114,99, - 104,32,105,115,32,98,97,115,101,100,32,111,110,32,115,121, - 115,46,112,97,116,104,95,104,111,111,107,115,32,97,110,100, - 32,115,121,115,46,112,97,116,104,95,105,109,112,111,114,116, - 101,114,95,99,97,99,104,101,46,10,32,32,32,32,32,32, - 32,32,78,90,9,110,97,109,101,115,112,97,99,101,41,7, - 114,8,0,0,0,114,37,0,0,0,114,12,1,0,0,114, - 124,0,0,0,114,160,0,0,0,114,162,0,0,0,114,234, - 0,0,0,41,6,114,174,0,0,0,114,123,0,0,0,114, - 37,0,0,0,114,183,0,0,0,114,168,0,0,0,114,11, - 1,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,114,184,0,0,0,214,4,0,0,115,26,0,0,0, - 0,6,8,1,6,1,14,1,8,1,4,1,10,1,6,1, - 4,3,6,1,16,1,4,2,6,2,122,20,80,97,116,104, - 70,105,110,100,101,114,46,102,105,110,100,95,115,112,101,99, - 99,3,0,0,0,0,0,0,0,4,0,0,0,4,0,0, - 0,67,0,0,0,115,30,0,0,0,124,0,160,0,124,1, - 124,2,161,2,125,3,124,3,100,1,107,8,114,24,100,1, - 83,0,124,3,106,1,83,0,41,2,122,170,102,105,110,100, - 32,116,104,101,32,109,111,100,117,108,101,32,111,110,32,115, - 121,115,46,112,97,116,104,32,111,114,32,39,112,97,116,104, - 39,32,98,97,115,101,100,32,111,110,32,115,121,115,46,112, - 97,116,104,95,104,111,111,107,115,32,97,110,100,10,32,32, - 32,32,32,32,32,32,115,121,115,46,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, - 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, - 32,32,32,32,32,32,78,41,2,114,184,0,0,0,114,124, - 0,0,0,41,4,114,174,0,0,0,114,123,0,0,0,114, - 37,0,0,0,114,168,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,6,0,0,0,114,185,0,0,0,238,4,0, - 0,115,8,0,0,0,0,8,12,1,8,1,4,1,122,22, - 80,97,116,104,70,105,110,100,101,114,46,102,105,110,100,95, - 109,111,100,117,108,101,41,1,78,41,2,78,78,41,1,78, - 41,12,114,109,0,0,0,114,108,0,0,0,114,110,0,0, - 0,114,111,0,0,0,114,186,0,0,0,114,0,1,0,0, - 114,5,1,0,0,114,8,1,0,0,114,9,1,0,0,114, - 12,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,6,0, - 0,0,114,255,0,0,0,120,4,0,0,115,20,0,0,0, - 12,4,12,8,12,13,12,22,12,15,2,1,12,31,2,1, - 12,23,2,1,114,255,0,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,3,0,0,0,64,0,0,0,115,90, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, - 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,101, - 6,90,7,100,6,100,7,132,0,90,8,100,8,100,9,132, - 0,90,9,100,19,100,11,100,12,132,1,90,10,100,13,100, - 14,132,0,90,11,101,12,100,15,100,16,132,0,131,1,90, - 13,100,17,100,18,132,0,90,14,100,10,83,0,41,20,218, - 10,70,105,108,101,70,105,110,100,101,114,122,172,70,105,108, - 101,45,98,97,115,101,100,32,102,105,110,100,101,114,46,10, - 10,32,32,32,32,73,110,116,101,114,97,99,116,105,111,110, - 115,32,119,105,116,104,32,116,104,101,32,102,105,108,101,32, - 115,121,115,116,101,109,32,97,114,101,32,99,97,99,104,101, - 100,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99, - 101,44,32,98,101,105,110,103,10,32,32,32,32,114,101,102, - 114,101,115,104,101,100,32,119,104,101,110,32,116,104,101,32, - 100,105,114,101,99,116,111,114,121,32,116,104,101,32,102,105, - 110,100,101,114,32,105,115,32,104,97,110,100,108,105,110,103, - 32,104,97,115,32,98,101,101,110,32,109,111,100,105,102,105, - 101,100,46,10,10,32,32,32,32,99,2,0,0,0,0,0, - 0,0,5,0,0,0,6,0,0,0,7,0,0,0,115,88, - 0,0,0,103,0,125,3,120,40,124,2,68,0,93,32,92, - 2,137,0,125,4,124,3,160,0,135,0,102,1,100,1,100, - 2,132,8,124,4,68,0,131,1,161,1,1,0,113,10,87, - 0,124,3,124,0,95,1,124,1,112,58,100,3,124,0,95, - 2,100,6,124,0,95,3,116,4,131,0,124,0,95,5,116, - 4,131,0,124,0,95,6,100,5,83,0,41,7,122,154,73, - 110,105,116,105,97,108,105,122,101,32,119,105,116,104,32,116, - 104,101,32,112,97,116,104,32,116,111,32,115,101,97,114,99, - 104,32,111,110,32,97,110,100,32,97,32,118,97,114,105,97, - 98,108,101,32,110,117,109,98,101,114,32,111,102,10,32,32, - 32,32,32,32,32,32,50,45,116,117,112,108,101,115,32,99, - 111,110,116,97,105,110,105,110,103,32,116,104,101,32,108,111, - 97,100,101,114,32,97,110,100,32,116,104,101,32,102,105,108, - 101,32,115,117,102,102,105,120,101,115,32,116,104,101,32,108, - 111,97,100,101,114,10,32,32,32,32,32,32,32,32,114,101, - 99,111,103,110,105,122,101,115,46,99,1,0,0,0,0,0, - 0,0,2,0,0,0,3,0,0,0,51,0,0,0,115,22, - 0,0,0,124,0,93,14,125,1,124,1,136,0,102,2,86, - 0,1,0,113,2,100,0,83,0,41,1,78,114,4,0,0, - 0,41,2,114,24,0,0,0,114,229,0,0,0,41,1,114, - 124,0,0,0,114,4,0,0,0,114,6,0,0,0,114,231, - 0,0,0,11,5,0,0,115,2,0,0,0,4,0,122,38, - 70,105,108,101,70,105,110,100,101,114,46,95,95,105,110,105, - 116,95,95,46,60,108,111,99,97,108,115,62,46,60,103,101, - 110,101,120,112,114,62,114,61,0,0,0,114,31,0,0,0, - 78,114,91,0,0,0,41,7,114,149,0,0,0,218,8,95, - 108,111,97,100,101,114,115,114,37,0,0,0,218,11,95,112, - 97,116,104,95,109,116,105,109,101,218,3,115,101,116,218,11, - 95,112,97,116,104,95,99,97,99,104,101,218,19,95,114,101, - 108,97,120,101,100,95,112,97,116,104,95,99,97,99,104,101, - 41,5,114,104,0,0,0,114,37,0,0,0,218,14,108,111, - 97,100,101,114,95,100,101,116,97,105,108,115,90,7,108,111, - 97,100,101,114,115,114,170,0,0,0,114,4,0,0,0,41, - 1,114,124,0,0,0,114,6,0,0,0,114,188,0,0,0, - 5,5,0,0,115,16,0,0,0,0,4,4,1,14,1,28, - 1,6,2,10,1,6,1,8,1,122,19,70,105,108,101,70, - 105,110,100,101,114,46,95,95,105,110,105,116,95,95,99,1, - 0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,67, - 0,0,0,115,10,0,0,0,100,3,124,0,95,0,100,2, - 83,0,41,4,122,31,73,110,118,97,108,105,100,97,116,101, - 32,116,104,101,32,100,105,114,101,99,116,111,114,121,32,109, - 116,105,109,101,46,114,31,0,0,0,78,114,91,0,0,0, - 41,1,114,15,1,0,0,41,1,114,104,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,0,1, - 0,0,19,5,0,0,115,2,0,0,0,0,2,122,28,70, - 105,108,101,70,105,110,100,101,114,46,105,110,118,97,108,105, - 100,97,116,101,95,99,97,99,104,101,115,99,2,0,0,0, - 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, - 115,42,0,0,0,124,0,160,0,124,1,161,1,125,2,124, - 2,100,1,107,8,114,26,100,1,103,0,102,2,83,0,124, - 2,106,1,124,2,106,2,112,38,103,0,102,2,83,0,41, - 2,122,197,84,114,121,32,116,111,32,102,105,110,100,32,97, - 32,108,111,97,100,101,114,32,102,111,114,32,116,104,101,32, - 115,112,101,99,105,102,105,101,100,32,109,111,100,117,108,101, - 44,32,111,114,32,116,104,101,32,110,97,109,101,115,112,97, - 99,101,10,32,32,32,32,32,32,32,32,112,97,99,107,97, - 103,101,32,112,111,114,116,105,111,110,115,46,32,82,101,116, - 117,114,110,115,32,40,108,111,97,100,101,114,44,32,108,105, - 115,116,45,111,102,45,112,111,114,116,105,111,110,115,41,46, - 10,10,32,32,32,32,32,32,32,32,84,104,105,115,32,109, - 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,46,32,32,85,115,101,32,102,105,110,100,95,115, - 112,101,99,40,41,32,105,110,115,116,101,97,100,46,10,10, - 32,32,32,32,32,32,32,32,78,41,3,114,184,0,0,0, - 114,124,0,0,0,114,160,0,0,0,41,3,114,104,0,0, - 0,114,123,0,0,0,114,168,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,114,121,0,0,0,25, - 5,0,0,115,8,0,0,0,0,7,10,1,8,1,8,1, - 122,22,70,105,108,101,70,105,110,100,101,114,46,102,105,110, - 100,95,108,111,97,100,101,114,99,6,0,0,0,0,0,0, - 0,7,0,0,0,6,0,0,0,67,0,0,0,115,26,0, - 0,0,124,1,124,2,124,3,131,2,125,6,116,0,124,2, - 124,3,124,6,124,4,100,1,141,4,83,0,41,2,78,41, - 2,114,124,0,0,0,114,160,0,0,0,41,1,114,171,0, - 0,0,41,7,114,104,0,0,0,114,169,0,0,0,114,123, - 0,0,0,114,37,0,0,0,90,4,115,109,115,108,114,183, - 0,0,0,114,124,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,114,12,1,0,0,37,5,0,0, - 115,6,0,0,0,0,1,10,1,8,1,122,20,70,105,108, - 101,70,105,110,100,101,114,46,95,103,101,116,95,115,112,101, - 99,78,99,3,0,0,0,0,0,0,0,14,0,0,0,16, - 0,0,0,67,0,0,0,115,98,1,0,0,100,1,125,3, - 124,1,160,0,100,2,161,1,100,3,25,0,125,4,121,24, - 116,1,124,0,106,2,112,34,116,3,160,4,161,0,131,1, - 106,5,125,5,87,0,110,24,4,0,116,6,107,10,114,66, - 1,0,1,0,1,0,100,10,125,5,89,0,110,2,88,0, - 124,5,124,0,106,7,107,3,114,92,124,0,160,8,161,0, - 1,0,124,5,124,0,95,7,116,9,131,0,114,114,124,0, - 106,10,125,6,124,4,160,11,161,0,125,7,110,10,124,0, - 106,12,125,6,124,4,125,7,124,7,124,6,107,6,114,218, - 116,13,124,0,106,2,124,4,131,2,125,8,120,72,124,0, - 106,14,68,0,93,54,92,2,125,9,125,10,100,5,124,9, - 23,0,125,11,116,13,124,8,124,11,131,2,125,12,116,15, - 124,12,131,1,114,152,124,0,160,16,124,10,124,1,124,12, - 124,8,103,1,124,2,161,5,83,0,113,152,87,0,116,17, - 124,8,131,1,125,3,120,88,124,0,106,14,68,0,93,78, - 92,2,125,9,125,10,116,13,124,0,106,2,124,4,124,9, - 23,0,131,2,125,12,116,18,106,19,100,6,124,12,100,3, - 100,7,141,3,1,0,124,7,124,9,23,0,124,6,107,6, - 114,226,116,15,124,12,131,1,114,226,124,0,160,16,124,10, - 124,1,124,12,100,8,124,2,161,5,83,0,113,226,87,0, - 124,3,144,1,114,94,116,18,160,19,100,9,124,8,161,2, - 1,0,116,18,160,20,124,1,100,8,161,2,125,13,124,8, - 103,1,124,13,95,21,124,13,83,0,100,8,83,0,41,11, - 122,111,84,114,121,32,116,111,32,102,105,110,100,32,97,32, - 115,112,101,99,32,102,111,114,32,116,104,101,32,115,112,101, - 99,105,102,105,101,100,32,109,111,100,117,108,101,46,10,10, - 32,32,32,32,32,32,32,32,82,101,116,117,114,110,115,32, - 116,104,101,32,109,97,116,99,104,105,110,103,32,115,112,101, - 99,44,32,111,114,32,78,111,110,101,32,105,102,32,110,111, - 116,32,102,111,117,110,100,46,10,32,32,32,32,32,32,32, - 32,70,114,61,0,0,0,114,59,0,0,0,114,31,0,0, - 0,114,188,0,0,0,122,9,116,114,121,105,110,103,32,123, - 125,41,1,90,9,118,101,114,98,111,115,105,116,121,78,122, - 25,112,111,115,115,105,98,108,101,32,110,97,109,101,115,112, - 97,99,101,32,102,111,114,32,123,125,114,91,0,0,0,41, - 22,114,34,0,0,0,114,41,0,0,0,114,37,0,0,0, - 114,3,0,0,0,114,47,0,0,0,114,223,0,0,0,114, - 42,0,0,0,114,15,1,0,0,218,11,95,102,105,108,108, - 95,99,97,99,104,101,114,7,0,0,0,114,18,1,0,0, - 114,92,0,0,0,114,17,1,0,0,114,30,0,0,0,114, - 14,1,0,0,114,46,0,0,0,114,12,1,0,0,114,48, - 0,0,0,114,118,0,0,0,114,132,0,0,0,114,164,0, - 0,0,114,160,0,0,0,41,14,114,104,0,0,0,114,123, - 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,151,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,169,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,168,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0, - 114,184,0,0,0,42,5,0,0,115,70,0,0,0,0,5, - 4,1,14,1,2,1,24,1,14,1,10,1,10,1,8,1, - 6,2,6,1,6,1,10,2,6,1,4,2,8,1,12,1, - 16,1,8,1,10,1,8,1,24,4,8,2,16,1,16,1, - 16,1,12,1,8,1,10,1,12,1,6,1,12,1,12,1, - 8,1,4,1,122,20,70,105,108,101,70,105,110,100,101,114, - 46,102,105,110,100,95,115,112,101,99,99,1,0,0,0,0, - 0,0,0,9,0,0,0,14,0,0,0,67,0,0,0,115, - 194,0,0,0,124,0,106,0,125,1,121,22,116,1,160,2, - 124,1,112,22,116,1,160,3,161,0,161,1,125,2,87,0, - 110,30,4,0,116,4,116,5,116,6,102,3,107,10,114,58, - 1,0,1,0,1,0,103,0,125,2,89,0,110,2,88,0, - 116,7,106,8,160,9,100,1,161,1,115,84,116,10,124,2, - 131,1,124,0,95,11,110,78,116,10,131,0,125,3,120,64, - 124,2,68,0,93,56,125,4,124,4,160,12,100,2,161,1, - 92,3,125,5,125,6,125,7,124,6,114,138,100,3,160,13, - 124,5,124,7,160,14,161,0,161,2,125,8,110,4,124,5, - 125,8,124,3,160,15,124,8,161,1,1,0,113,96,87,0, - 124,3,124,0,95,11,116,7,106,8,160,9,116,16,161,1, - 114,190,100,4,100,5,132,0,124,2,68,0,131,1,124,0, - 95,17,100,6,83,0,41,7,122,68,70,105,108,108,32,116, - 104,101,32,99,97,99,104,101,32,111,102,32,112,111,116,101, - 110,116,105,97,108,32,109,111,100,117,108,101,115,32,97,110, - 100,32,112,97,99,107,97,103,101,115,32,102,111,114,32,116, - 104,105,115,32,100,105,114,101,99,116,111,114,121,46,114,0, - 0,0,0,114,61,0,0,0,122,5,123,125,46,123,125,99, - 1,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 83,0,0,0,115,20,0,0,0,104,0,124,0,93,12,125, - 1,124,1,160,0,161,0,146,2,113,4,83,0,114,4,0, - 0,0,41,1,114,92,0,0,0,41,2,114,24,0,0,0, - 90,2,102,110,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,250,9,60,115,101,116,99,111,109,112,62,119,5, - 0,0,115,2,0,0,0,6,0,122,41,70,105,108,101,70, - 105,110,100,101,114,46,95,102,105,108,108,95,99,97,99,104, - 101,46,60,108,111,99,97,108,115,62,46,60,115,101,116,99, - 111,109,112,62,78,41,18,114,37,0,0,0,114,3,0,0, - 0,90,7,108,105,115,116,100,105,114,114,47,0,0,0,114, - 6,1,0,0,218,15,80,101,114,109,105,115,115,105,111,110, - 69,114,114,111,114,218,18,78,111,116,65,68,105,114,101,99, - 116,111,114,121,69,114,114,111,114,114,8,0,0,0,114,9, - 0,0,0,114,10,0,0,0,114,16,1,0,0,114,17,1, - 0,0,114,87,0,0,0,114,50,0,0,0,114,92,0,0, - 0,218,3,97,100,100,114,11,0,0,0,114,18,1,0,0, - 41,9,114,104,0,0,0,114,37,0,0,0,90,8,99,111, - 110,116,101,110,116,115,90,21,108,111,119,101,114,95,115,117, - 102,102,105,120,95,99,111,110,116,101,110,116,115,114,251,0, - 0,0,114,102,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,6,0,0,0,114,20,1,0,0,90, - 5,0,0,115,34,0,0,0,0,2,6,1,2,1,22,1, - 20,3,10,3,12,1,12,7,6,1,10,1,16,1,4,1, - 18,2,4,1,14,1,6,1,12,1,122,22,70,105,108,101, - 70,105,110,100,101,114,46,95,102,105,108,108,95,99,97,99, - 104,101,99,1,0,0,0,0,0,0,0,3,0,0,0,3, - 0,0,0,7,0,0,0,115,18,0,0,0,135,0,135,1, - 102,2,100,1,100,2,132,8,125,2,124,2,83,0,41,3, - 97,20,1,0,0,65,32,99,108,97,115,115,32,109,101,116, - 104,111,100,32,119,104,105,99,104,32,114,101,116,117,114,110, - 115,32,97,32,99,108,111,115,117,114,101,32,116,111,32,117, - 115,101,32,111,110,32,115,121,115,46,112,97,116,104,95,104, - 111,111,107,10,32,32,32,32,32,32,32,32,119,104,105,99, - 104,32,119,105,108,108,32,114,101,116,117,114,110,32,97,110, - 32,105,110,115,116,97,110,99,101,32,117,115,105,110,103,32, - 116,104,101,32,115,112,101,99,105,102,105,101,100,32,108,111, - 97,100,101,114,115,32,97,110,100,32,116,104,101,32,112,97, - 116,104,10,32,32,32,32,32,32,32,32,99,97,108,108,101, - 100,32,111,110,32,116,104,101,32,99,108,111,115,117,114,101, - 46,10,10,32,32,32,32,32,32,32,32,73,102,32,116,104, - 101,32,112,97,116,104,32,99,97,108,108,101,100,32,111,110, - 32,116,104,101,32,99,108,111,115,117,114,101,32,105,115,32, - 110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,44, - 32,73,109,112,111,114,116,69,114,114,111,114,32,105,115,10, - 32,32,32,32,32,32,32,32,114,97,105,115,101,100,46,10, - 10,32,32,32,32,32,32,32,32,99,1,0,0,0,0,0, - 0,0,1,0,0,0,4,0,0,0,19,0,0,0,115,34, - 0,0,0,116,0,124,0,131,1,115,20,116,1,100,1,124, - 0,100,2,141,2,130,1,136,0,124,0,102,1,136,1,158, - 2,142,0,83,0,41,3,122,45,80,97,116,104,32,104,111, - 111,107,32,102,111,114,32,105,109,112,111,114,116,108,105,98, - 46,109,97,99,104,105,110,101,114,121,46,70,105,108,101,70, - 105,110,100,101,114,46,122,30,111,110,108,121,32,100,105,114, - 101,99,116,111,114,105,101,115,32,97,114,101,32,115,117,112, - 112,111,114,116,101,100,41,1,114,37,0,0,0,41,2,114, - 48,0,0,0,114,103,0,0,0,41,1,114,37,0,0,0, - 41,2,114,174,0,0,0,114,19,1,0,0,114,4,0,0, - 0,114,6,0,0,0,218,24,112,97,116,104,95,104,111,111, - 107,95,102,111,114,95,70,105,108,101,70,105,110,100,101,114, - 131,5,0,0,115,6,0,0,0,0,2,8,1,12,1,122, - 54,70,105,108,101,70,105,110,100,101,114,46,112,97,116,104, - 95,104,111,111,107,46,60,108,111,99,97,108,115,62,46,112, - 97,116,104,95,104,111,111,107,95,102,111,114,95,70,105,108, - 101,70,105,110,100,101,114,114,4,0,0,0,41,3,114,174, - 0,0,0,114,19,1,0,0,114,25,1,0,0,114,4,0, - 0,0,41,2,114,174,0,0,0,114,19,1,0,0,114,6, - 0,0,0,218,9,112,97,116,104,95,104,111,111,107,121,5, - 0,0,115,4,0,0,0,0,10,14,6,122,20,70,105,108, - 101,70,105,110,100,101,114,46,112,97,116,104,95,104,111,111, - 107,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,115,12,0,0,0,100,1,160,0,124, - 0,106,1,161,1,83,0,41,2,78,122,16,70,105,108,101, - 70,105,110,100,101,114,40,123,33,114,125,41,41,2,114,50, - 0,0,0,114,37,0,0,0,41,1,114,104,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,250, - 0,0,0,139,5,0,0,115,2,0,0,0,0,1,122,19, - 70,105,108,101,70,105,110,100,101,114,46,95,95,114,101,112, - 114,95,95,41,1,78,41,15,114,109,0,0,0,114,108,0, - 0,0,114,110,0,0,0,114,111,0,0,0,114,188,0,0, - 0,114,0,1,0,0,114,127,0,0,0,114,185,0,0,0, - 114,121,0,0,0,114,12,1,0,0,114,184,0,0,0,114, - 20,1,0,0,114,186,0,0,0,114,26,1,0,0,114,250, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,114,13,1,0,0,252,4,0,0, - 115,18,0,0,0,12,9,8,14,8,4,4,2,8,12,8, - 5,10,48,8,31,12,18,114,13,1,0,0,99,4,0,0, - 0,0,0,0,0,6,0,0,0,11,0,0,0,67,0,0, - 0,115,146,0,0,0,124,0,160,0,100,1,161,1,125,4, - 124,0,160,0,100,2,161,1,125,5,124,4,115,66,124,5, - 114,36,124,5,106,1,125,4,110,30,124,2,124,3,107,2, - 114,56,116,2,124,1,124,2,131,2,125,4,110,10,116,3, - 124,1,124,2,131,2,125,4,124,5,115,84,116,4,124,1, - 124,2,124,4,100,3,141,3,125,5,121,36,124,5,124,0, - 100,2,60,0,124,4,124,0,100,1,60,0,124,2,124,0, - 100,4,60,0,124,3,124,0,100,5,60,0,87,0,110,20, - 4,0,116,5,107,10,114,140,1,0,1,0,1,0,89,0, - 110,2,88,0,100,0,83,0,41,6,78,218,10,95,95,108, - 111,97,100,101,114,95,95,218,8,95,95,115,112,101,99,95, - 95,41,1,114,124,0,0,0,90,8,95,95,102,105,108,101, - 95,95,90,10,95,95,99,97,99,104,101,100,95,95,41,6, - 218,3,103,101,116,114,124,0,0,0,114,227,0,0,0,114, - 222,0,0,0,114,171,0,0,0,218,9,69,120,99,101,112, - 116,105,111,110,41,6,90,2,110,115,114,102,0,0,0,90, - 8,112,97,116,104,110,97,109,101,90,9,99,112,97,116,104, - 110,97,109,101,114,124,0,0,0,114,168,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,218,14,95, - 102,105,120,95,117,112,95,109,111,100,117,108,101,145,5,0, - 0,115,34,0,0,0,0,2,10,1,10,1,4,1,4,1, - 8,1,8,1,12,2,10,1,4,1,14,1,2,1,8,1, - 8,1,8,1,12,1,14,2,114,31,1,0,0,99,0,0, - 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, - 0,0,115,38,0,0,0,116,0,116,1,160,2,161,0,102, - 2,125,0,116,3,116,4,102,2,125,1,116,5,116,6,102, - 2,125,2,124,0,124,1,124,2,103,3,83,0,41,1,122, - 95,82,101,116,117,114,110,115,32,97,32,108,105,115,116,32, - 111,102,32,102,105,108,101,45,98,97,115,101,100,32,109,111, - 100,117,108,101,32,108,111,97,100,101,114,115,46,10,10,32, - 32,32,32,69,97,99,104,32,105,116,101,109,32,105,115,32, - 97,32,116,117,112,108,101,32,40,108,111,97,100,101,114,44, - 32,115,117,102,102,105,120,101,115,41,46,10,32,32,32,32, - 41,7,114,228,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,222,0,0,0,114,88,0,0,0,114,227,0,0,0,114, - 78,0,0,0,41,3,90,10,101,120,116,101,110,115,105,111, - 110,115,90,6,115,111,117,114,99,101,90,8,98,121,116,101, - 99,111,100,101,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,114,165,0,0,0,168,5,0,0,115,8,0,0, - 0,0,5,12,1,8,1,8,1,114,165,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,156,1,0,0,124,0,97,0,116,0,106,1, - 97,1,116,0,106,2,97,2,116,1,106,3,116,4,25,0, - 125,1,120,56,100,26,68,0,93,48,125,2,124,2,116,1, - 106,3,107,7,114,58,116,0,160,5,124,2,161,1,125,3, - 110,10,116,1,106,3,124,2,25,0,125,3,116,6,124,1, - 124,2,124,3,131,3,1,0,113,32,87,0,100,5,100,6, - 103,1,102,2,100,7,100,8,100,6,103,2,102,2,102,2, - 125,4,120,118,124,4,68,0,93,102,92,2,125,5,125,6, - 116,7,100,9,100,10,132,0,124,6,68,0,131,1,131,1, - 115,142,116,8,130,1,124,6,100,11,25,0,125,7,124,5, - 116,1,106,3,107,6,114,174,116,1,106,3,124,5,25,0, - 125,8,80,0,113,112,121,16,116,0,160,5,124,5,161,1, - 125,8,80,0,87,0,113,112,4,0,116,9,107,10,114,212, - 1,0,1,0,1,0,119,112,89,0,113,112,88,0,113,112, - 87,0,116,9,100,12,131,1,130,1,116,6,124,1,100,13, - 124,8,131,3,1,0,116,6,124,1,100,14,124,7,131,3, - 1,0,116,6,124,1,100,15,100,16,160,10,124,6,161,1, - 131,3,1,0,116,0,160,5,100,17,161,1,125,9,116,6, - 124,1,100,17,124,9,131,3,1,0,116,0,160,5,100,18, - 161,1,125,10,116,6,124,1,100,18,124,10,131,3,1,0, - 124,5,100,7,107,2,144,1,114,88,116,0,160,5,100,19, - 161,1,125,11,116,6,124,1,100,20,124,11,131,3,1,0, - 116,6,124,1,100,21,116,11,131,0,131,3,1,0,116,12, - 160,13,116,2,160,14,161,0,161,1,1,0,124,5,100,7, - 107,2,144,1,114,152,116,15,160,16,100,22,161,1,1,0, - 100,23,116,12,107,6,144,1,114,152,100,24,116,17,95,18, - 100,25,83,0,41,27,122,205,83,101,116,117,112,32,116,104, - 101,32,112,97,116,104,45,98,97,115,101,100,32,105,109,112, - 111,114,116,101,114,115,32,102,111,114,32,105,109,112,111,114, - 116,108,105,98,32,98,121,32,105,109,112,111,114,116,105,110, - 103,32,110,101,101,100,101,100,10,32,32,32,32,98,117,105, - 108,116,45,105,110,32,109,111,100,117,108,101,115,32,97,110, - 100,32,105,110,106,101,99,116,105,110,103,32,116,104,101,109, - 32,105,110,116,111,32,116,104,101,32,103,108,111,98,97,108, - 32,110,97,109,101,115,112,97,99,101,46,10,10,32,32,32, - 32,79,116,104,101,114,32,99,111,109,112,111,110,101,110,116, - 115,32,97,114,101,32,101,120,116,114,97,99,116,101,100,32, - 102,114,111,109,32,116,104,101,32,99,111,114,101,32,98,111, - 111,116,115,116,114,97,112,32,109,111,100,117,108,101,46,10, - 10,32,32,32,32,114,52,0,0,0,114,63,0,0,0,218, - 8,98,117,105,108,116,105,110,115,114,142,0,0,0,90,5, - 112,111,115,105,120,250,1,47,90,2,110,116,250,1,92,99, - 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 115,0,0,0,115,26,0,0,0,124,0,93,18,125,1,116, - 0,124,1,131,1,100,0,107,2,86,0,1,0,113,2,100, - 1,83,0,41,2,114,31,0,0,0,78,41,1,114,33,0, - 0,0,41,2,114,24,0,0,0,114,81,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,231,0, - 0,0,204,5,0,0,115,2,0,0,0,4,0,122,25,95, - 115,101,116,117,112,46,60,108,111,99,97,108,115,62,46,60, - 103,101,110,101,120,112,114,62,114,62,0,0,0,122,30,105, - 109,112,111,114,116,108,105,98,32,114,101,113,117,105,114,101, - 115,32,112,111,115,105,120,32,111,114,32,110,116,114,3,0, - 0,0,114,27,0,0,0,114,23,0,0,0,114,32,0,0, - 0,90,7,95,116,104,114,101,97,100,90,8,95,119,101,97, - 107,114,101,102,90,6,119,105,110,114,101,103,114,173,0,0, - 0,114,7,0,0,0,122,4,46,112,121,119,122,6,95,100, - 46,112,121,100,84,78,41,4,114,52,0,0,0,114,63,0, - 0,0,114,33,1,0,0,114,142,0,0,0,41,19,114,118, - 0,0,0,114,8,0,0,0,114,145,0,0,0,114,243,0, - 0,0,114,109,0,0,0,90,18,95,98,117,105,108,116,105, - 110,95,102,114,111,109,95,110,97,109,101,114,113,0,0,0, - 218,3,97,108,108,114,153,0,0,0,114,103,0,0,0,114, - 28,0,0,0,114,13,0,0,0,114,233,0,0,0,114,149, - 0,0,0,114,32,1,0,0,114,88,0,0,0,114,167,0, - 0,0,114,172,0,0,0,114,176,0,0,0,41,12,218,17, - 95,98,111,111,116,115,116,114,97,112,95,109,111,100,117,108, - 101,90,11,115,101,108,102,95,109,111,100,117,108,101,90,12, - 98,117,105,108,116,105,110,95,110,97,109,101,90,14,98,117, - 105,108,116,105,110,95,109,111,100,117,108,101,90,10,111,115, - 95,100,101,116,97,105,108,115,90,10,98,117,105,108,116,105, - 110,95,111,115,114,23,0,0,0,114,27,0,0,0,90,9, - 111,115,95,109,111,100,117,108,101,90,13,116,104,114,101,97, - 100,95,109,111,100,117,108,101,90,14,119,101,97,107,114,101, - 102,95,109,111,100,117,108,101,90,13,119,105,110,114,101,103, - 95,109,111,100,117,108,101,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,218,6,95,115,101,116,117,112,179,5, - 0,0,115,76,0,0,0,0,8,4,1,6,1,6,3,10, - 1,10,1,10,1,12,2,10,1,16,3,22,1,14,2,22, - 1,8,1,10,1,10,1,4,2,2,1,10,1,6,1,14, - 1,12,2,8,1,12,1,12,1,18,3,10,1,12,3,10, - 1,12,3,10,1,10,1,12,3,14,1,14,1,10,1,10, - 1,10,1,114,38,1,0,0,99,1,0,0,0,0,0,0, - 0,2,0,0,0,4,0,0,0,67,0,0,0,115,50,0, - 0,0,116,0,124,0,131,1,1,0,116,1,131,0,125,1, - 116,2,106,3,160,4,116,5,106,6,124,1,142,0,103,1, - 161,1,1,0,116,2,106,7,160,8,116,9,161,1,1,0, - 100,1,83,0,41,2,122,41,73,110,115,116,97,108,108,32, + 101,115,99,2,0,0,0,0,0,0,0,3,0,0,0,3, + 0,0,0,67,0,0,0,115,42,0,0,0,124,0,160,0, + 124,1,161,1,125,2,124,2,100,1,107,8,114,26,100,1, + 103,0,102,2,83,0,124,2,106,1,124,2,106,2,112,38, + 103,0,102,2,83,0,41,2,122,197,84,114,121,32,116,111, + 32,102,105,110,100,32,97,32,108,111,97,100,101,114,32,102, + 111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100, + 32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,32, + 110,97,109,101,115,112,97,99,101,10,32,32,32,32,32,32, + 32,32,112,97,99,107,97,103,101,32,112,111,114,116,105,111, + 110,115,46,32,82,101,116,117,114,110,115,32,40,108,111,97, + 100,101,114,44,32,108,105,115,116,45,111,102,45,112,111,114, + 116,105,111,110,115,41,46,10,10,32,32,32,32,32,32,32, + 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, + 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, + 32,102,105,110,100,95,115,112,101,99,40,41,32,105,110,115, + 116,101,97,100,46,10,10,32,32,32,32,32,32,32,32,78, + 41,3,114,182,0,0,0,114,122,0,0,0,114,158,0,0, + 0,41,3,114,102,0,0,0,114,121,0,0,0,114,166,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,119,0,0,0,25,5,0,0,115,8,0,0,0,0, + 7,10,1,8,1,8,1,122,22,70,105,108,101,70,105,110, + 100,101,114,46,102,105,110,100,95,108,111,97,100,101,114,99, + 6,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0, + 67,0,0,0,115,26,0,0,0,124,1,124,2,124,3,131, + 2,125,6,116,0,124,2,124,3,124,6,124,4,100,1,141, + 4,83,0,41,2,78,41,2,114,122,0,0,0,114,158,0, + 0,0,41,1,114,169,0,0,0,41,7,114,102,0,0,0, + 114,167,0,0,0,114,121,0,0,0,114,35,0,0,0,90, + 4,115,109,115,108,114,181,0,0,0,114,122,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,10, + 1,0,0,37,5,0,0,115,6,0,0,0,0,1,10,1, + 8,1,122,20,70,105,108,101,70,105,110,100,101,114,46,95, + 103,101,116,95,115,112,101,99,78,99,3,0,0,0,0,0, + 0,0,14,0,0,0,16,0,0,0,67,0,0,0,115,98, + 1,0,0,100,1,125,3,124,1,160,0,100,2,161,1,100, + 3,25,0,125,4,121,24,116,1,124,0,106,2,112,34,116, + 3,160,4,161,0,131,1,106,5,125,5,87,0,110,24,4, + 0,116,6,107,10,114,66,1,0,1,0,1,0,100,4,125, + 5,89,0,110,2,88,0,124,5,124,0,106,7,107,3,114, + 92,124,0,160,8,161,0,1,0,124,5,124,0,95,7,116, + 9,131,0,114,114,124,0,106,10,125,6,124,4,160,11,161, + 0,125,7,110,10,124,0,106,12,125,6,124,4,125,7,124, + 7,124,6,107,6,114,218,116,13,124,0,106,2,124,4,131, + 2,125,8,120,72,124,0,106,14,68,0,93,54,92,2,125, + 9,125,10,100,5,124,9,23,0,125,11,116,13,124,8,124, + 11,131,2,125,12,116,15,124,12,131,1,114,152,124,0,160, + 16,124,10,124,1,124,12,124,8,103,1,124,2,161,5,83, + 0,113,152,87,0,116,17,124,8,131,1,125,3,120,88,124, + 0,106,14,68,0,93,78,92,2,125,9,125,10,116,13,124, + 0,106,2,124,4,124,9,23,0,131,2,125,12,116,18,106, + 19,100,6,124,12,100,3,100,7,141,3,1,0,124,7,124, + 9,23,0,124,6,107,6,114,226,116,15,124,12,131,1,114, + 226,124,0,160,16,124,10,124,1,124,12,100,8,124,2,161, + 5,83,0,113,226,87,0,124,3,144,1,114,94,116,18,160, + 19,100,9,124,8,161,2,1,0,116,18,160,20,124,1,100, + 8,161,2,125,13,124,8,103,1,124,13,95,21,124,13,83, + 0,100,8,83,0,41,10,122,111,84,114,121,32,116,111,32, + 102,105,110,100,32,97,32,115,112,101,99,32,102,111,114,32, + 116,104,101,32,115,112,101,99,105,102,105,101,100,32,109,111, + 100,117,108,101,46,10,10,32,32,32,32,32,32,32,32,82, + 101,116,117,114,110,115,32,116,104,101,32,109,97,116,99,104, + 105,110,103,32,115,112,101,99,44,32,111,114,32,78,111,110, + 101,32,105,102,32,110,111,116,32,102,111,117,110,100,46,10, + 32,32,32,32,32,32,32,32,70,114,59,0,0,0,114,57, + 0,0,0,114,89,0,0,0,114,186,0,0,0,122,9,116, + 114,121,105,110,103,32,123,125,41,1,90,9,118,101,114,98, + 111,115,105,116,121,78,122,25,112,111,115,115,105,98,108,101, + 32,110,97,109,101,115,112,97,99,101,32,102,111,114,32,123, + 125,41,22,114,32,0,0,0,114,39,0,0,0,114,35,0, + 0,0,114,1,0,0,0,114,45,0,0,0,114,221,0,0, + 0,114,40,0,0,0,114,13,1,0,0,218,11,95,102,105, + 108,108,95,99,97,99,104,101,114,5,0,0,0,114,16,1, + 0,0,114,90,0,0,0,114,15,1,0,0,114,28,0,0, + 0,114,12,1,0,0,114,44,0,0,0,114,10,1,0,0, + 114,46,0,0,0,114,116,0,0,0,114,130,0,0,0,114, + 162,0,0,0,114,158,0,0,0,41,14,114,102,0,0,0, + 114,121,0,0,0,114,181,0,0,0,90,12,105,115,95,110, + 97,109,101,115,112,97,99,101,90,11,116,97,105,108,95,109, + 111,100,117,108,101,114,149,0,0,0,90,5,99,97,99,104, + 101,90,12,99,97,99,104,101,95,109,111,100,117,108,101,90, + 9,98,97,115,101,95,112,97,116,104,114,227,0,0,0,114, + 167,0,0,0,90,13,105,110,105,116,95,102,105,108,101,110, + 97,109,101,90,9,102,117,108,108,95,112,97,116,104,114,166, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,182,0,0,0,42,5,0,0,115,70,0,0,0, + 0,5,4,1,14,1,2,1,24,1,14,1,10,1,10,1, + 8,1,6,2,6,1,6,1,10,2,6,1,4,2,8,1, + 12,1,16,1,8,1,10,1,8,1,24,4,8,2,16,1, + 16,1,16,1,12,1,8,1,10,1,12,1,6,1,12,1, + 12,1,8,1,4,1,122,20,70,105,108,101,70,105,110,100, + 101,114,46,102,105,110,100,95,115,112,101,99,99,1,0,0, + 0,0,0,0,0,9,0,0,0,14,0,0,0,67,0,0, + 0,115,194,0,0,0,124,0,106,0,125,1,121,22,116,1, + 160,2,124,1,112,22,116,1,160,3,161,0,161,1,125,2, + 87,0,110,30,4,0,116,4,116,5,116,6,102,3,107,10, + 114,58,1,0,1,0,1,0,103,0,125,2,89,0,110,2, + 88,0,116,7,106,8,160,9,100,1,161,1,115,84,116,10, + 124,2,131,1,124,0,95,11,110,78,116,10,131,0,125,3, + 120,64,124,2,68,0,93,56,125,4,124,4,160,12,100,2, + 161,1,92,3,125,5,125,6,125,7,124,6,114,138,100,3, + 160,13,124,5,124,7,160,14,161,0,161,2,125,8,110,4, + 124,5,125,8,124,3,160,15,124,8,161,1,1,0,113,96, + 87,0,124,3,124,0,95,11,116,7,106,8,160,9,116,16, + 161,1,114,190,100,4,100,5,132,0,124,2,68,0,131,1, + 124,0,95,17,100,6,83,0,41,7,122,68,70,105,108,108, + 32,116,104,101,32,99,97,99,104,101,32,111,102,32,112,111, + 116,101,110,116,105,97,108,32,109,111,100,117,108,101,115,32, + 97,110,100,32,112,97,99,107,97,103,101,115,32,102,111,114, + 32,116,104,105,115,32,100,105,114,101,99,116,111,114,121,46, + 114,0,0,0,0,114,59,0,0,0,122,5,123,125,46,123, + 125,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,83,0,0,0,115,20,0,0,0,104,0,124,0,93, + 12,125,1,124,1,160,0,161,0,146,2,113,4,83,0,114, + 2,0,0,0,41,1,114,90,0,0,0,41,2,114,22,0, + 0,0,90,2,102,110,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,250,9,60,115,101,116,99,111,109,112,62, + 119,5,0,0,115,2,0,0,0,6,0,122,41,70,105,108, + 101,70,105,110,100,101,114,46,95,102,105,108,108,95,99,97, + 99,104,101,46,60,108,111,99,97,108,115,62,46,60,115,101, + 116,99,111,109,112,62,78,41,18,114,35,0,0,0,114,1, + 0,0,0,90,7,108,105,115,116,100,105,114,114,45,0,0, + 0,114,4,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,6,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,14,1,0,0,114, + 15,1,0,0,114,85,0,0,0,114,48,0,0,0,114,90, + 0,0,0,218,3,97,100,100,114,9,0,0,0,114,16,1, + 0,0,41,9,114,102,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, + 249,0,0,0,114,100,0,0,0,114,239,0,0,0,114,227, + 0,0,0,90,8,110,101,119,95,110,97,109,101,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,18,1,0, + 0,90,5,0,0,115,34,0,0,0,0,2,6,1,2,1, + 22,1,20,3,10,3,12,1,12,7,6,1,10,1,16,1, + 4,1,18,2,4,1,14,1,6,1,12,1,122,22,70,105, + 108,101,70,105,110,100,101,114,46,95,102,105,108,108,95,99, + 97,99,104,101,99,1,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,7,0,0,0,115,18,0,0,0,135,0, + 135,1,102,2,100,1,100,2,132,8,125,2,124,2,83,0, + 41,3,97,20,1,0,0,65,32,99,108,97,115,115,32,109, + 101,116,104,111,100,32,119,104,105,99,104,32,114,101,116,117, + 114,110,115,32,97,32,99,108,111,115,117,114,101,32,116,111, + 32,117,115,101,32,111,110,32,115,121,115,46,112,97,116,104, + 95,104,111,111,107,10,32,32,32,32,32,32,32,32,119,104, + 105,99,104,32,119,105,108,108,32,114,101,116,117,114,110,32, + 97,110,32,105,110,115,116,97,110,99,101,32,117,115,105,110, + 103,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, + 108,111,97,100,101,114,115,32,97,110,100,32,116,104,101,32, + 112,97,116,104,10,32,32,32,32,32,32,32,32,99,97,108, + 108,101,100,32,111,110,32,116,104,101,32,99,108,111,115,117, + 114,101,46,10,10,32,32,32,32,32,32,32,32,73,102,32, + 116,104,101,32,112,97,116,104,32,99,97,108,108,101,100,32, + 111,110,32,116,104,101,32,99,108,111,115,117,114,101,32,105, + 115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114, + 121,44,32,73,109,112,111,114,116,69,114,114,111,114,32,105, + 115,10,32,32,32,32,32,32,32,32,114,97,105,115,101,100, + 46,10,10,32,32,32,32,32,32,32,32,99,1,0,0,0, + 0,0,0,0,1,0,0,0,4,0,0,0,19,0,0,0, + 115,34,0,0,0,116,0,124,0,131,1,115,20,116,1,100, + 1,124,0,100,2,141,2,130,1,136,0,124,0,102,1,136, + 1,158,2,142,0,83,0,41,3,122,45,80,97,116,104,32, + 104,111,111,107,32,102,111,114,32,105,109,112,111,114,116,108, + 105,98,46,109,97,99,104,105,110,101,114,121,46,70,105,108, + 101,70,105,110,100,101,114,46,122,30,111,110,108,121,32,100, + 105,114,101,99,116,111,114,105,101,115,32,97,114,101,32,115, + 117,112,112,111,114,116,101,100,41,1,114,35,0,0,0,41, + 2,114,46,0,0,0,114,101,0,0,0,41,1,114,35,0, + 0,0,41,2,114,172,0,0,0,114,17,1,0,0,114,2, + 0,0,0,114,4,0,0,0,218,24,112,97,116,104,95,104, + 111,111,107,95,102,111,114,95,70,105,108,101,70,105,110,100, + 101,114,131,5,0,0,115,6,0,0,0,0,2,8,1,12, + 1,122,54,70,105,108,101,70,105,110,100,101,114,46,112,97, + 116,104,95,104,111,111,107,46,60,108,111,99,97,108,115,62, + 46,112,97,116,104,95,104,111,111,107,95,102,111,114,95,70, + 105,108,101,70,105,110,100,101,114,114,2,0,0,0,41,3, + 114,172,0,0,0,114,17,1,0,0,114,23,1,0,0,114, + 2,0,0,0,41,2,114,172,0,0,0,114,17,1,0,0, + 114,4,0,0,0,218,9,112,97,116,104,95,104,111,111,107, + 121,5,0,0,115,4,0,0,0,0,10,14,6,122,20,70, + 105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104, + 111,111,107,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,12,0,0,0,100,1,160, + 0,124,0,106,1,161,1,83,0,41,2,78,122,16,70,105, + 108,101,70,105,110,100,101,114,40,123,33,114,125,41,41,2, + 114,48,0,0,0,114,35,0,0,0,41,1,114,102,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,248,0,0,0,139,5,0,0,115,2,0,0,0,0,1, + 122,19,70,105,108,101,70,105,110,100,101,114,46,95,95,114, + 101,112,114,95,95,41,1,78,41,15,114,107,0,0,0,114, + 106,0,0,0,114,108,0,0,0,114,109,0,0,0,114,186, + 0,0,0,114,254,0,0,0,114,125,0,0,0,114,183,0, + 0,0,114,119,0,0,0,114,10,1,0,0,114,182,0,0, + 0,114,18,1,0,0,114,184,0,0,0,114,24,1,0,0, + 114,248,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,11,1,0,0,252,4, + 0,0,115,18,0,0,0,12,9,8,14,8,4,4,2,8, + 12,8,5,10,48,8,31,12,18,114,11,1,0,0,99,4, + 0,0,0,0,0,0,0,6,0,0,0,11,0,0,0,67, + 0,0,0,115,146,0,0,0,124,0,160,0,100,1,161,1, + 125,4,124,0,160,0,100,2,161,1,125,5,124,4,115,66, + 124,5,114,36,124,5,106,1,125,4,110,30,124,2,124,3, + 107,2,114,56,116,2,124,1,124,2,131,2,125,4,110,10, + 116,3,124,1,124,2,131,2,125,4,124,5,115,84,116,4, + 124,1,124,2,124,4,100,3,141,3,125,5,121,36,124,5, + 124,0,100,2,60,0,124,4,124,0,100,1,60,0,124,2, + 124,0,100,4,60,0,124,3,124,0,100,5,60,0,87,0, + 110,20,4,0,116,5,107,10,114,140,1,0,1,0,1,0, + 89,0,110,2,88,0,100,0,83,0,41,6,78,218,10,95, + 95,108,111,97,100,101,114,95,95,218,8,95,95,115,112,101, + 99,95,95,41,1,114,122,0,0,0,90,8,95,95,102,105, + 108,101,95,95,90,10,95,95,99,97,99,104,101,100,95,95, + 41,6,218,3,103,101,116,114,122,0,0,0,114,225,0,0, + 0,114,220,0,0,0,114,169,0,0,0,218,9,69,120,99, + 101,112,116,105,111,110,41,6,90,2,110,115,114,100,0,0, + 0,90,8,112,97,116,104,110,97,109,101,90,9,99,112,97, + 116,104,110,97,109,101,114,122,0,0,0,114,166,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 14,95,102,105,120,95,117,112,95,109,111,100,117,108,101,145, + 5,0,0,115,34,0,0,0,0,2,10,1,10,1,4,1, + 4,1,8,1,8,1,12,2,10,1,4,1,14,1,2,1, + 8,1,8,1,8,1,12,1,14,2,114,29,1,0,0,99, + 0,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, + 67,0,0,0,115,38,0,0,0,116,0,116,1,160,2,161, + 0,102,2,125,0,116,3,116,4,102,2,125,1,116,5,116, + 6,102,2,125,2,124,0,124,1,124,2,103,3,83,0,41, + 1,122,95,82,101,116,117,114,110,115,32,97,32,108,105,115, + 116,32,111,102,32,102,105,108,101,45,98,97,115,101,100,32, + 109,111,100,117,108,101,32,108,111,97,100,101,114,115,46,10, + 10,32,32,32,32,69,97,99,104,32,105,116,101,109,32,105, + 115,32,97,32,116,117,112,108,101,32,40,108,111,97,100,101, + 114,44,32,115,117,102,102,105,120,101,115,41,46,10,32,32, + 32,32,41,7,114,226,0,0,0,114,143,0,0,0,218,18, + 101,120,116,101,110,115,105,111,110,95,115,117,102,102,105,120, + 101,115,114,220,0,0,0,114,86,0,0,0,114,225,0,0, + 0,114,76,0,0,0,41,3,90,10,101,120,116,101,110,115, + 105,111,110,115,90,6,115,111,117,114,99,101,90,8,98,121, + 116,101,99,111,100,101,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,163,0,0,0,168,5,0,0,115,8, + 0,0,0,0,5,12,1,8,1,8,1,114,163,0,0,0, + 99,1,0,0,0,0,0,0,0,12,0,0,0,12,0,0, + 0,67,0,0,0,115,156,1,0,0,124,0,97,0,116,0, + 106,1,97,1,116,0,106,2,97,2,116,1,106,3,116,4, + 25,0,125,1,120,56,100,1,68,0,93,48,125,2,124,2, + 116,1,106,3,107,7,114,58,116,0,160,5,124,2,161,1, + 125,3,110,10,116,1,106,3,124,2,25,0,125,3,116,6, + 124,1,124,2,124,3,131,3,1,0,113,32,87,0,100,2, + 100,3,103,1,102,2,100,4,100,5,100,3,103,2,102,2, + 102,2,125,4,120,118,124,4,68,0,93,102,92,2,125,5, + 125,6,116,7,100,6,100,7,132,0,124,6,68,0,131,1, + 131,1,115,142,116,8,130,1,124,6,100,8,25,0,125,7, + 124,5,116,1,106,3,107,6,114,174,116,1,106,3,124,5, + 25,0,125,8,80,0,113,112,121,16,116,0,160,5,124,5, + 161,1,125,8,80,0,87,0,113,112,4,0,116,9,107,10, + 114,212,1,0,1,0,1,0,119,112,89,0,113,112,88,0, + 113,112,87,0,116,9,100,9,131,1,130,1,116,6,124,1, + 100,10,124,8,131,3,1,0,116,6,124,1,100,11,124,7, + 131,3,1,0,116,6,124,1,100,12,100,13,160,10,124,6, + 161,1,131,3,1,0,116,0,160,5,100,14,161,1,125,9, + 116,6,124,1,100,14,124,9,131,3,1,0,116,0,160,5, + 100,15,161,1,125,10,116,6,124,1,100,15,124,10,131,3, + 1,0,124,5,100,4,107,2,144,1,114,88,116,0,160,5, + 100,16,161,1,125,11,116,6,124,1,100,17,124,11,131,3, + 1,0,116,6,124,1,100,18,116,11,131,0,131,3,1,0, + 116,12,160,13,116,2,160,14,161,0,161,1,1,0,124,5, + 100,4,107,2,144,1,114,152,116,15,160,16,100,19,161,1, + 1,0,100,20,116,12,107,6,144,1,114,152,100,21,116,17, + 95,18,100,22,83,0,41,23,122,205,83,101,116,117,112,32, 116,104,101,32,112,97,116,104,45,98,97,115,101,100,32,105, - 109,112,111,114,116,32,99,111,109,112,111,110,101,110,116,115, - 46,78,41,10,114,38,1,0,0,114,165,0,0,0,114,8, - 0,0,0,114,4,1,0,0,114,149,0,0,0,114,13,1, - 0,0,114,26,1,0,0,218,9,109,101,116,97,95,112,97, - 116,104,114,167,0,0,0,114,255,0,0,0,41,2,114,37, - 1,0,0,90,17,115,117,112,112,111,114,116,101,100,95,108, - 111,97,100,101,114,115,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,218,8,95,105,110,115,116,97,108,108,243, - 5,0,0,115,8,0,0,0,0,2,8,1,6,1,20,1, - 114,40,1,0,0,41,1,114,0,0,0,0,41,2,114,1, - 0,0,0,114,2,0,0,0,41,1,114,49,0,0,0,41, - 1,78,41,3,78,78,78,41,2,114,62,0,0,0,114,62, - 0,0,0,41,1,84,41,1,78,41,1,78,41,61,114,111, - 0,0,0,114,12,0,0,0,90,37,95,67,65,83,69,95, - 73,78,83,69,78,83,73,84,73,86,69,95,80,76,65,84, - 70,79,82,77,83,95,66,89,84,69,83,95,75,69,89,114, - 11,0,0,0,114,13,0,0,0,114,19,0,0,0,114,21, - 0,0,0,114,30,0,0,0,114,40,0,0,0,114,41,0, - 0,0,114,45,0,0,0,114,46,0,0,0,114,48,0,0, - 0,114,58,0,0,0,218,4,116,121,112,101,218,8,95,95, - 99,111,100,101,95,95,114,144,0,0,0,114,17,0,0,0, - 114,131,0,0,0,114,16,0,0,0,114,20,0,0,0,114, - 211,0,0,0,114,77,0,0,0,114,76,0,0,0,114,88, - 0,0,0,114,78,0,0,0,90,23,68,69,66,85,71,95, - 66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,69, - 83,90,27,79,80,84,73,77,73,90,69,68,95,66,89,84, - 69,67,79,68,69,95,83,85,70,70,73,88,69,83,114,83, - 0,0,0,114,89,0,0,0,114,95,0,0,0,114,99,0, - 0,0,114,101,0,0,0,114,120,0,0,0,114,127,0,0, - 0,114,135,0,0,0,114,139,0,0,0,114,141,0,0,0, - 114,147,0,0,0,114,152,0,0,0,114,154,0,0,0,114, - 159,0,0,0,218,6,111,98,106,101,99,116,114,166,0,0, - 0,114,171,0,0,0,114,172,0,0,0,114,187,0,0,0, - 114,197,0,0,0,114,214,0,0,0,114,222,0,0,0,114, - 227,0,0,0,114,233,0,0,0,114,228,0,0,0,114,234, - 0,0,0,114,253,0,0,0,114,255,0,0,0,114,13,1, - 0,0,114,31,1,0,0,114,165,0,0,0,114,38,1,0, - 0,114,40,1,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,218,8,60,109,111,100, - 117,108,101,62,24,0,0,0,115,116,0,0,0,4,0,4, - 1,4,1,2,1,6,3,8,17,8,5,8,5,8,6,8, - 12,8,10,8,9,8,5,8,7,10,22,10,126,16,1,12, - 2,4,1,4,2,6,2,6,2,8,2,16,45,8,34,8, - 19,8,12,8,12,8,28,8,17,8,33,8,28,8,24,10, - 13,10,10,10,11,8,14,6,3,4,1,14,67,14,64,14, - 29,16,127,0,17,14,41,18,45,18,26,4,3,18,53,14, - 60,14,42,14,127,0,5,14,127,0,22,10,23,8,11,8, - 64, + 109,112,111,114,116,101,114,115,32,102,111,114,32,105,109,112, + 111,114,116,108,105,98,32,98,121,32,105,109,112,111,114,116, + 105,110,103,32,110,101,101,100,101,100,10,32,32,32,32,98, + 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32, + 97,110,100,32,105,110,106,101,99,116,105,110,103,32,116,104, + 101,109,32,105,110,116,111,32,116,104,101,32,103,108,111,98, + 97,108,32,110,97,109,101,115,112,97,99,101,46,10,10,32, + 32,32,32,79,116,104,101,114,32,99,111,109,112,111,110,101, + 110,116,115,32,97,114,101,32,101,120,116,114,97,99,116,101, + 100,32,102,114,111,109,32,116,104,101,32,99,111,114,101,32, + 98,111,111,116,115,116,114,97,112,32,109,111,100,117,108,101, + 46,10,10,32,32,32,32,41,4,114,50,0,0,0,114,61, + 0,0,0,218,8,98,117,105,108,116,105,110,115,114,140,0, + 0,0,90,5,112,111,115,105,120,250,1,47,90,2,110,116, + 250,1,92,99,1,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,115,0,0,0,115,26,0,0,0,124,0,93, + 18,125,1,116,0,124,1,131,1,100,0,107,2,86,0,1, + 0,113,2,100,1,83,0,41,2,114,29,0,0,0,78,41, + 1,114,31,0,0,0,41,2,114,22,0,0,0,114,79,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,229,0,0,0,204,5,0,0,115,2,0,0,0,4, + 0,122,25,95,115,101,116,117,112,46,60,108,111,99,97,108, + 115,62,46,60,103,101,110,101,120,112,114,62,114,60,0,0, + 0,122,30,105,109,112,111,114,116,108,105,98,32,114,101,113, + 117,105,114,101,115,32,112,111,115,105,120,32,111,114,32,110, + 116,114,1,0,0,0,114,25,0,0,0,114,21,0,0,0, + 114,30,0,0,0,90,7,95,116,104,114,101,97,100,90,8, + 95,119,101,97,107,114,101,102,90,6,119,105,110,114,101,103, + 114,171,0,0,0,114,5,0,0,0,122,4,46,112,121,119, + 122,6,95,100,46,112,121,100,84,78,41,19,114,116,0,0, + 0,114,6,0,0,0,114,143,0,0,0,114,241,0,0,0, + 114,107,0,0,0,90,18,95,98,117,105,108,116,105,110,95, + 102,114,111,109,95,110,97,109,101,114,111,0,0,0,218,3, + 97,108,108,114,151,0,0,0,114,101,0,0,0,114,26,0, + 0,0,114,11,0,0,0,114,231,0,0,0,114,147,0,0, + 0,114,30,1,0,0,114,86,0,0,0,114,165,0,0,0, + 114,170,0,0,0,114,174,0,0,0,41,12,218,17,95,98, + 111,111,116,115,116,114,97,112,95,109,111,100,117,108,101,90, + 11,115,101,108,102,95,109,111,100,117,108,101,90,12,98,117, + 105,108,116,105,110,95,110,97,109,101,90,14,98,117,105,108, + 116,105,110,95,109,111,100,117,108,101,90,10,111,115,95,100, + 101,116,97,105,108,115,90,10,98,117,105,108,116,105,110,95, + 111,115,114,21,0,0,0,114,25,0,0,0,90,9,111,115, + 95,109,111,100,117,108,101,90,13,116,104,114,101,97,100,95, + 109,111,100,117,108,101,90,14,119,101,97,107,114,101,102,95, + 109,111,100,117,108,101,90,13,119,105,110,114,101,103,95,109, + 111,100,117,108,101,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,218,6,95,115,101,116,117,112,179,5,0,0, + 115,76,0,0,0,0,8,4,1,6,1,6,3,10,1,10, + 1,10,1,12,2,10,1,16,3,22,1,14,2,22,1,8, + 1,10,1,10,1,4,2,2,1,10,1,6,1,14,1,12, + 2,8,1,12,1,12,1,18,3,10,1,12,3,10,1,12, + 3,10,1,10,1,12,3,14,1,14,1,10,1,10,1,10, + 1,114,36,1,0,0,99,1,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,67,0,0,0,115,50,0,0,0, + 116,0,124,0,131,1,1,0,116,1,131,0,125,1,116,2, + 106,3,160,4,116,5,106,6,124,1,142,0,103,1,161,1, + 1,0,116,2,106,7,160,8,116,9,161,1,1,0,100,1, + 83,0,41,2,122,41,73,110,115,116,97,108,108,32,116,104, + 101,32,112,97,116,104,45,98,97,115,101,100,32,105,109,112, + 111,114,116,32,99,111,109,112,111,110,101,110,116,115,46,78, + 41,10,114,36,1,0,0,114,163,0,0,0,114,6,0,0, + 0,114,2,1,0,0,114,147,0,0,0,114,11,1,0,0, + 114,24,1,0,0,218,9,109,101,116,97,95,112,97,116,104, + 114,165,0,0,0,114,253,0,0,0,41,2,114,35,1,0, + 0,90,17,115,117,112,112,111,114,116,101,100,95,108,111,97, + 100,101,114,115,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,218,8,95,105,110,115,116,97,108,108,243,5,0, + 0,115,8,0,0,0,0,2,8,1,6,1,20,1,114,38, + 1,0,0,41,1,114,47,0,0,0,41,1,78,41,3,78, + 78,78,41,2,114,60,0,0,0,114,60,0,0,0,41,1, + 84,41,1,78,41,1,78,41,61,114,109,0,0,0,114,10, + 0,0,0,90,37,95,67,65,83,69,95,73,78,83,69,78, + 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, + 95,66,89,84,69,83,95,75,69,89,114,9,0,0,0,114, + 11,0,0,0,114,17,0,0,0,114,19,0,0,0,114,28, + 0,0,0,114,38,0,0,0,114,39,0,0,0,114,43,0, + 0,0,114,44,0,0,0,114,46,0,0,0,114,56,0,0, + 0,218,4,116,121,112,101,218,8,95,95,99,111,100,101,95, + 95,114,142,0,0,0,114,15,0,0,0,114,129,0,0,0, + 114,14,0,0,0,114,18,0,0,0,114,209,0,0,0,114, + 75,0,0,0,114,74,0,0,0,114,86,0,0,0,114,76, + 0,0,0,90,23,68,69,66,85,71,95,66,89,84,69,67, + 79,68,69,95,83,85,70,70,73,88,69,83,90,27,79,80, + 84,73,77,73,90,69,68,95,66,89,84,69,67,79,68,69, + 95,83,85,70,70,73,88,69,83,114,81,0,0,0,114,87, + 0,0,0,114,93,0,0,0,114,97,0,0,0,114,99,0, + 0,0,114,118,0,0,0,114,125,0,0,0,114,133,0,0, + 0,114,137,0,0,0,114,139,0,0,0,114,145,0,0,0, + 114,150,0,0,0,114,152,0,0,0,114,157,0,0,0,218, + 6,111,98,106,101,99,116,114,164,0,0,0,114,169,0,0, + 0,114,170,0,0,0,114,185,0,0,0,114,195,0,0,0, + 114,212,0,0,0,114,220,0,0,0,114,225,0,0,0,114, + 231,0,0,0,114,226,0,0,0,114,232,0,0,0,114,251, + 0,0,0,114,253,0,0,0,114,11,1,0,0,114,29,1, + 0,0,114,163,0,0,0,114,36,1,0,0,114,38,1,0, + 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,8,60,109,111,100,117,108,101,62,24, + 0,0,0,115,116,0,0,0,4,0,4,1,4,1,2,1, + 6,3,8,17,8,5,8,5,8,6,8,12,8,10,8,9, + 8,5,8,7,10,22,10,126,16,1,12,2,4,1,4,2, + 6,2,6,2,8,2,16,45,8,34,8,19,8,12,8,12, + 8,28,8,17,8,33,8,28,8,24,10,13,10,10,10,11, + 8,14,6,3,4,1,14,67,14,64,14,29,16,127,0,17, + 14,41,18,45,18,26,4,3,18,53,14,60,14,42,14,127, + 0,5,14,127,0,22,10,23,8,11,8,64, }; diff --git a/Python/peephole.c b/Python/peephole.c index 1bee7102d9c..3c5290fadc0 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -218,153 +218,6 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end); } -/* Replace LOAD_CONST c1, LOAD_CONST c2, BINOP - with LOAD_CONST binop(c1,c2) - The consts table must still be in list form so that the - new constant can be appended. - Called with codestr pointing to the BINOP. - Abandons the transformation if the folding fails (i.e. 1+'a'). - If the new constant is a sequence, only folds when the size - is below a threshold value. That keeps pyc files from - becoming large in the presence of code like: (None,)*1000. -*/ -static Py_ssize_t -fold_binops_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, - Py_ssize_t opcode_end, unsigned char opcode, - PyObject *consts, PyObject **objs) -{ - PyObject *newconst, *v, *w; - Py_ssize_t len_consts, size; - - /* Pre-conditions */ - assert(PyList_CheckExact(consts)); - len_consts = PyList_GET_SIZE(consts); - - /* Create new constant */ - v = objs[0]; - w = objs[1]; - switch (opcode) { - case BINARY_POWER: - newconst = PyNumber_Power(v, w, Py_None); - break; - case BINARY_MULTIPLY: - newconst = PyNumber_Multiply(v, w); - break; - case BINARY_TRUE_DIVIDE: - newconst = PyNumber_TrueDivide(v, w); - break; - case BINARY_FLOOR_DIVIDE: - newconst = PyNumber_FloorDivide(v, w); - break; - case BINARY_MODULO: - newconst = PyNumber_Remainder(v, w); - break; - case BINARY_ADD: - newconst = PyNumber_Add(v, w); - break; - case BINARY_SUBTRACT: - newconst = PyNumber_Subtract(v, w); - break; - case BINARY_SUBSCR: - newconst = PyObject_GetItem(v, w); - break; - case BINARY_LSHIFT: - newconst = PyNumber_Lshift(v, w); - break; - case BINARY_RSHIFT: - newconst = PyNumber_Rshift(v, w); - break; - case BINARY_AND: - newconst = PyNumber_And(v, w); - break; - case BINARY_XOR: - newconst = PyNumber_Xor(v, w); - break; - case BINARY_OR: - newconst = PyNumber_Or(v, w); - break; - default: - /* Called with an unknown opcode */ - PyErr_Format(PyExc_SystemError, - "unexpected binary operation %d on a constant", - opcode); - return -1; - } - if (newconst == NULL) { - if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { - PyErr_Clear(); - } - return -1; - } - size = PyObject_Size(newconst); - if (size == -1) { - if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { - return -1; - } - PyErr_Clear(); - } else if (size > 20) { - Py_DECREF(newconst); - return -1; - } - - /* Append folded constant into consts table */ - if (PyList_Append(consts, newconst)) { - Py_DECREF(newconst); - return -1; - } - Py_DECREF(newconst); - - return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end); -} - -static Py_ssize_t -fold_unaryops_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, - Py_ssize_t opcode_end, unsigned char opcode, - PyObject *consts, PyObject *v) -{ - PyObject *newconst; - Py_ssize_t len_consts; - - /* Pre-conditions */ - assert(PyList_CheckExact(consts)); - len_consts = PyList_GET_SIZE(consts); - - /* Create new constant */ - switch (opcode) { - case UNARY_NEGATIVE: - newconst = PyNumber_Negative(v); - break; - case UNARY_INVERT: - newconst = PyNumber_Invert(v); - break; - case UNARY_POSITIVE: - newconst = PyNumber_Positive(v); - break; - default: - /* Called with an unknown opcode */ - PyErr_Format(PyExc_SystemError, - "unexpected unary operation %d on a constant", - opcode); - return -1; - } - if (newconst == NULL) { - if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { - PyErr_Clear(); - } - return -1; - } - - /* Append folded constant into consts table */ - if (PyList_Append(consts, newconst)) { - Py_DECREF(newconst); - PyErr_Clear(); - return -1; - } - Py_DECREF(newconst); - - return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end); -} - static unsigned int * markblocks(_Py_CODEUNIT *code, Py_ssize_t len) { @@ -566,52 +419,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } break; - /* Fold binary ops on constants. - LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ - case BINARY_POWER: - case BINARY_MULTIPLY: - case BINARY_TRUE_DIVIDE: - case BINARY_FLOOR_DIVIDE: - case BINARY_MODULO: - case BINARY_ADD: - case BINARY_SUBTRACT: - case BINARY_SUBSCR: - case BINARY_LSHIFT: - case BINARY_RSHIFT: - case BINARY_AND: - case BINARY_XOR: - case BINARY_OR: - if (CONST_STACK_LEN() < 2) - break; - h = lastn_const_start(codestr, op_start, 2); - if (ISBASICBLOCK(blocks, h, op_start)) { - h = fold_binops_on_constants(codestr, h, i + 1, opcode, - consts, CONST_STACK_LASTN(2)); - if (h >= 0) { - CONST_STACK_POP(2); - CONST_STACK_PUSH_OP(h); - } - } - break; - - /* Fold unary ops on constants. - LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */ - case UNARY_NEGATIVE: - case UNARY_INVERT: - case UNARY_POSITIVE: - if (CONST_STACK_LEN() < 1) - break; - h = lastn_const_start(codestr, op_start, 1); - if (ISBASICBLOCK(blocks, h, op_start)) { - h = fold_unaryops_on_constants(codestr, h, i + 1, opcode, - consts, *CONST_STACK_LASTN(1)); - if (h >= 0) { - CONST_STACK_POP(1); - CONST_STACK_PUSH_OP(h); - } - } - break; - /* Simplify conditional jump to conditional jump where the result of the first test implies the success of a similar test or the failure of the opposite test. From solipsis at pitrou.net Thu Dec 14 04:13:07 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 14 Dec 2017 09:13:07 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171214091307.47848.087EB60054D6A106@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-2, 0, 2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog_zt969', '--timeout', '7200'] From webhook-mailer at python.org Thu Dec 14 05:39:37 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 14 Dec 2017 10:39:37 -0000 Subject: [Python-checkins] bpo-32302: Fix distutils bdist_wininst for CRT v142 (#4851) Message-ID: https://github.com/python/cpython/commit/9e7c136ad8bc8e8eec50c2a8ae5ff02752f695a2 commit: 9e7c136ad8bc8e8eec50c2a8ae5ff02752f695a2 branch: master author: Victor Stinner committer: GitHub date: 2017-12-14T11:39:34+01:00 summary: bpo-32302: Fix distutils bdist_wininst for CRT v142 (#4851) CRT v142 is binary compatible with CRT v140. files: A Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst M Lib/distutils/command/bdist_wininst.py diff --git a/Lib/distutils/command/bdist_wininst.py b/Lib/distutils/command/bdist_wininst.py index 6309c3e248c..83f00732657 100644 --- a/Lib/distutils/command/bdist_wininst.py +++ b/Lib/distutils/command/bdist_wininst.py @@ -338,8 +338,8 @@ def get_exe_bytes(self): bv = '14.0' else: bv = '.'.join(CRT_ASSEMBLY_VERSION.split('.', 2)[:2]) - if bv == '14.11': - # v141 and v140 are binary compatible, + if bv in ('14.11', '14.12'): + # v142, v141 and v140 are binary compatible, # so keep using the 14.0 stub. bv = '14.0' diff --git a/Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst b/Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst new file mode 100644 index 00000000000..abe51f094a8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst @@ -0,0 +1,2 @@ +Fix bdist_wininst of distutils for CRT v142: it binary compatible with CRT +v140. From webhook-mailer at python.org Thu Dec 14 05:59:48 2017 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Thu, 14 Dec 2017 10:59:48 -0000 Subject: [Python-checkins] bpo-32225: Implementation of PEP 562 (#4731) Message-ID: https://github.com/python/cpython/commit/5364b5cd7571f2dfa75acd37b388c14ac33fef73 commit: 5364b5cd7571f2dfa75acd37b388c14ac33fef73 branch: master author: Ivan Levkivskyi committer: GitHub date: 2017-12-14T11:59:44+01:00 summary: bpo-32225: Implementation of PEP 562 (#4731) Implement PEP 562: module __getattr__ and __dir__. The implementation simply updates module_getattro and module_dir. files: A Lib/test/bad_getattr.py A Lib/test/bad_getattr2.py A Lib/test/bad_getattr3.py A Lib/test/good_getattr.py A Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-33-47.bpo-32225.ucKjvw.rst M Doc/reference/datamodel.rst M Doc/whatsnew/3.7.rst M Lib/test/test_module.py M Objects/moduleobject.c diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 153b58b4fbf..790339cd47b 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1512,6 +1512,51 @@ access (use of, assignment to, or deletion of ``x.name``) for class instances. returned. :func:`dir` converts the returned sequence to a list and sorts it. +Customizing module attribute access +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. index:: + single: __getattr__ (module attribute) + single: __dir__ (module attribute) + single: __class__ (module attribute) + +Special names ``__getattr__`` and ``__dir__`` can be also used to customize +access to module attributes. The ``__getattr__`` function at the module level +should accept one argument which is the name of an attribute and return the +computed value or raise an :exc:`AttributeError`. If an attribute is +not found on a module object through the normal lookup, i.e. +:meth:`object.__getattribute__`, then ``__getattr__`` is searched in +the module ``__dict__`` before raising an :exc:`AttributeError`. If found, +it is called with the attribute name and the result is returned. + +The ``__dir__`` function should accept no arguments, and return a list of +strings that represents the names accessible on module. If present, this +function overrides the standard :func:`dir` search on a module. + +For a more fine grained customization of the module behavior (setting +attributes, properties, etc.), one can set the ``__class__`` attribute of +a module object to a subclass of :class:`types.ModuleType`. For example:: + + import sys + from types import ModuleType + + class VerboseModule(ModuleType): + def __repr__(self): + return f'Verbose {self.__name__}' + + def __setattr__(self, attr, value): + print(f'Setting {attr}...') + setattr(self, attr, value) + + sys.modules[__name__].__class__ = VerboseModule + +.. note:: + Defining module ``__getattr__`` and setting module ``__class__`` only + affect lookups made using the attribute access syntax -- directly accessing + the module globals (whether by code within the module, or via a reference + to the module's globals dictionary) is unaffected. + + .. _descriptors: Implementing Descriptors diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index d6d0861d5d5..3574b53ad18 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -159,6 +159,24 @@ effort will be made to add such support. PEP written by Erik M. Bray; implementation by Masayuki Yamamoto. +PEP 562: Customization of access to module attributes +----------------------------------------------------- + +It is sometimes convenient to customize or otherwise have control over access +to module attributes. A typical example is managing deprecation warnings. +Typical workarounds are assigning ``__class__`` of a module object to +a custom subclass of :class:`types.ModuleType` or replacing the ``sys.modules`` +item with a custom wrapper instance. This procedure is now simplified by +recognizing ``__getattr__`` defined directly in a module that would act like +a normal ``__getattr__`` method, except that it will be defined on module +*instances*. + +.. seealso:: + + :pep:`562` -- Module ``__getattr__`` and ``__dir__`` + PEP written and implemented by Ivan Levkivskyi + + PEP 564: Add new time functions with nanosecond resolution ---------------------------------------------------------- diff --git a/Lib/test/bad_getattr.py b/Lib/test/bad_getattr.py new file mode 100644 index 00000000000..16f901b13b8 --- /dev/null +++ b/Lib/test/bad_getattr.py @@ -0,0 +1,4 @@ +x = 1 + +__getattr__ = "Surprise!" +__dir__ = "Surprise again!" diff --git a/Lib/test/bad_getattr2.py b/Lib/test/bad_getattr2.py new file mode 100644 index 00000000000..0a52a53b54b --- /dev/null +++ b/Lib/test/bad_getattr2.py @@ -0,0 +1,7 @@ +def __getattr__(): + "Bad one" + +x = 1 + +def __dir__(bad_sig): + return [] diff --git a/Lib/test/bad_getattr3.py b/Lib/test/bad_getattr3.py new file mode 100644 index 00000000000..0d5f9266c71 --- /dev/null +++ b/Lib/test/bad_getattr3.py @@ -0,0 +1,5 @@ +def __getattr__(name): + if name != 'delgetattr': + raise AttributeError + del globals()['__getattr__'] + raise AttributeError diff --git a/Lib/test/good_getattr.py b/Lib/test/good_getattr.py new file mode 100644 index 00000000000..7d27de6262a --- /dev/null +++ b/Lib/test/good_getattr.py @@ -0,0 +1,11 @@ +x = 1 + +def __dir__(): + return ['a', 'b', 'c'] + +def __getattr__(name): + if name == "yolo": + raise AttributeError("Deprecated, use whatever instead") + return f"There is {name}" + +y = 2 diff --git a/Lib/test/test_module.py b/Lib/test/test_module.py index 6d0d59407ed..efe9a8ed5e5 100644 --- a/Lib/test/test_module.py +++ b/Lib/test/test_module.py @@ -125,6 +125,57 @@ def test_weakref(self): gc_collect() self.assertIs(wr(), None) + def test_module_getattr(self): + import test.good_getattr as gga + from test.good_getattr import test + self.assertEqual(test, "There is test") + self.assertEqual(gga.x, 1) + self.assertEqual(gga.y, 2) + with self.assertRaisesRegex(AttributeError, + "Deprecated, use whatever instead"): + gga.yolo + self.assertEqual(gga.whatever, "There is whatever") + del sys.modules['test.good_getattr'] + + def test_module_getattr_errors(self): + import test.bad_getattr as bga + from test import bad_getattr2 + self.assertEqual(bga.x, 1) + self.assertEqual(bad_getattr2.x, 1) + with self.assertRaises(TypeError): + bga.nope + with self.assertRaises(TypeError): + bad_getattr2.nope + del sys.modules['test.bad_getattr'] + if 'test.bad_getattr2' in sys.modules: + del sys.modules['test.bad_getattr2'] + + def test_module_dir(self): + import test.good_getattr as gga + self.assertEqual(dir(gga), ['a', 'b', 'c']) + del sys.modules['test.good_getattr'] + + def test_module_dir_errors(self): + import test.bad_getattr as bga + from test import bad_getattr2 + with self.assertRaises(TypeError): + dir(bga) + with self.assertRaises(TypeError): + dir(bad_getattr2) + del sys.modules['test.bad_getattr'] + if 'test.bad_getattr2' in sys.modules: + del sys.modules['test.bad_getattr2'] + + def test_module_getattr_tricky(self): + from test import bad_getattr3 + # these lookups should not crash + with self.assertRaises(AttributeError): + bad_getattr3.one + with self.assertRaises(AttributeError): + bad_getattr3.delgetattr + if 'test.bad_getattr3' in sys.modules: + del sys.modules['test.bad_getattr3'] + def test_module_repr_minimal(self): # reprs when modules have no __file__, __name__, or __loader__ m = ModuleType('foo') diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-33-47.bpo-32225.ucKjvw.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-33-47.bpo-32225.ucKjvw.rst new file mode 100644 index 00000000000..5cde073dd63 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-33-47.bpo-32225.ucKjvw.rst @@ -0,0 +1,2 @@ +PEP 562: Add support for module ``__getattr__`` and ``__dir__``. Implemented by Ivan +Levkivskyi. diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 29732633da1..d6cde402433 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -679,12 +679,19 @@ module_repr(PyModuleObject *m) static PyObject* module_getattro(PyModuleObject *m, PyObject *name) { - PyObject *attr, *mod_name; + PyObject *attr, *mod_name, *getattr; attr = PyObject_GenericGetAttr((PyObject *)m, name); - if (attr || !PyErr_ExceptionMatches(PyExc_AttributeError)) + if (attr || !PyErr_ExceptionMatches(PyExc_AttributeError)) { return attr; + } PyErr_Clear(); if (m->md_dict) { + _Py_IDENTIFIER(__getattr__); + getattr = _PyDict_GetItemId(m->md_dict, &PyId___getattr__); + if (getattr) { + PyObject* stack[1] = {name}; + return _PyObject_FastCall(getattr, stack, 1); + } _Py_IDENTIFIER(__name__); mod_name = _PyDict_GetItemId(m->md_dict, &PyId___name__); if (mod_name && PyUnicode_Check(mod_name)) { @@ -730,8 +737,15 @@ module_dir(PyObject *self, PyObject *args) PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__); if (dict != NULL) { - if (PyDict_Check(dict)) - result = PyDict_Keys(dict); + if (PyDict_Check(dict)) { + PyObject *dirfunc = PyDict_GetItemString(dict, "__dir__"); + if (dirfunc) { + result = _PyObject_CallNoArg(dirfunc); + } + else { + result = PyDict_Keys(dict); + } + } else { const char *name = PyModule_GetName(self); if (name) From webhook-mailer at python.org Thu Dec 14 06:00:54 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 14 Dec 2017 11:00:54 -0000 Subject: [Python-checkins] bpo-32302: Fix distutils bdist_wininst for CRT v142 (GH-4851) (#4861) Message-ID: https://github.com/python/cpython/commit/645fa19f15cddeec8d882a9e1420173e7516f0e4 commit: 645fa19f15cddeec8d882a9e1420173e7516f0e4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Victor Stinner date: 2017-12-14T12:00:50+01:00 summary: bpo-32302: Fix distutils bdist_wininst for CRT v142 (GH-4851) (#4861) CRT v142 is binary compatible with CRT v140. (cherry picked from commit 9e7c136ad8bc8e8eec50c2a8ae5ff02752f695a2) files: A Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst M Lib/distutils/command/bdist_wininst.py diff --git a/Lib/distutils/command/bdist_wininst.py b/Lib/distutils/command/bdist_wininst.py index 6309c3e248c..83f00732657 100644 --- a/Lib/distutils/command/bdist_wininst.py +++ b/Lib/distutils/command/bdist_wininst.py @@ -338,8 +338,8 @@ def get_exe_bytes(self): bv = '14.0' else: bv = '.'.join(CRT_ASSEMBLY_VERSION.split('.', 2)[:2]) - if bv == '14.11': - # v141 and v140 are binary compatible, + if bv in ('14.11', '14.12'): + # v142, v141 and v140 are binary compatible, # so keep using the 14.0 stub. bv = '14.0' diff --git a/Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst b/Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst new file mode 100644 index 00000000000..abe51f094a8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-13-22-38-08.bpo-32302.othtTr.rst @@ -0,0 +1,2 @@ +Fix bdist_wininst of distutils for CRT v142: it binary compatible with CRT +v140. From webhook-mailer at python.org Thu Dec 14 06:04:56 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 14 Dec 2017 11:04:56 -0000 Subject: [Python-checkins] bpo-32297: Few misspellings found in Python source code comments. (#4803) Message-ID: https://github.com/python/cpython/commit/53f7a7c2814fbfd8a29200926601a32fa48bacb3 commit: 53f7a7c2814fbfd8a29200926601a32fa48bacb3 branch: master author: Mike committer: Andrew Svetlov date: 2017-12-14T13:04:53+02:00 summary: bpo-32297: Few misspellings found in Python source code comments. (#4803) * Fix multiple typos in code comments * Add spacing in comments (test_logging.py, test_math.py) * Fix spaces at the beginning of comments in test_logging.py files: M Doc/includes/email-read-alternative.py M Lib/ctypes/test/test_pep3118.py M Lib/ctypes/test/test_structures.py M Lib/email/quoprimime.py M Lib/http/client.py M Lib/os.py M Lib/tarfile.py M Lib/test/_test_multiprocessing.py M Lib/test/test_baseexception.py M Lib/test/test_class.py M Lib/test/test_collections.py M Lib/test/test_dataclasses.py M Lib/test/test_functools.py M Lib/test/test_generators.py M Lib/test/test_importlib/builtin/test_finder.py M Lib/test/test_importlib/source/test_file_loader.py M Lib/test/test_inspect.py M Lib/test/test_io.py M Lib/test/test_largefile.py M Lib/test/test_logging.py M Lib/test/test_math.py M Lib/test/test_parser.py M Lib/test/test_random.py M Lib/test/test_site.py M Lib/test/test_socket.py M Lib/test/test_ssl.py M Lib/test/test_sys_settrace.py M Lib/test/test_xml_etree.py M Lib/test/test_zipapp.py M Lib/tkinter/test/test_ttk/test_functions.py M Lib/tkinter/ttk.py M Lib/turtledemo/__main__.py M Lib/unittest/test/testmock/testmagicmethods.py M Lib/xml/etree/ElementTree.py M Lib/xmlrpc/client.py M Mac/BuildScript/build-installer.py M Modules/faulthandler.c M Tools/c-globals/check-c-globals.py M setup.py diff --git a/Doc/includes/email-read-alternative.py b/Doc/includes/email-read-alternative.py index 3f5ab24c0fb..5ea84e62584 100644 --- a/Doc/includes/email-read-alternative.py +++ b/Doc/includes/email-read-alternative.py @@ -21,7 +21,7 @@ print('From:', msg['from']) print('Subject:', msg['subject']) -# If we want to print a priview of the message content, we can extract whatever +# If we want to print a preview of the message content, we can extract whatever # the least formatted payload is and print the first three lines. Of course, # if the message has no plain text part printing the first three lines of html # is probably useless, but this is just a conceptual example. diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py index f3c0e23e53e..81e8ca7638f 100644 --- a/Lib/ctypes/test/test_pep3118.py +++ b/Lib/ctypes/test/test_pep3118.py @@ -188,7 +188,7 @@ class Complete(Structure): (PackedPoint, "B", (), PackedPoint), (Point2, "T{ integer diff --git a/Lib/tarfile.py b/Lib/tarfile.py index efc1f3b9f7f..0b8d31f85cf 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1058,7 +1058,7 @@ def frombuf(cls, buf, encoding, errors): # The old GNU sparse format occupies some of the unused # space in the buffer for up to 4 sparse structures. - # Save the them for later processing in _proc_sparse(). + # Save them for later processing in _proc_sparse(). if obj.type == GNUTYPE_SPARSE: pos = 386 structs = [] diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index dbca2d89ed1..60385536992 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4115,7 +4115,7 @@ def test_noforkbomb(self): # class TestForkAwareThreadLock(unittest.TestCase): - # We recurisvely start processes. Issue #17555 meant that the + # We recursively start processes. Issue #17555 meant that the # after fork registry would get duplicate entries for the same # lock. The size of the registry at generation n was ~2**n. diff --git a/Lib/test/test_baseexception.py b/Lib/test/test_baseexception.py index c055ee3d83c..c32468269a7 100644 --- a/Lib/test/test_baseexception.py +++ b/Lib/test/test_baseexception.py @@ -163,7 +163,7 @@ def test_raise_string(self): self.raise_fails("spam") def test_catch_non_BaseException(self): - # Tryinng to catch an object that does not inherit from BaseException + # Trying to catch an object that does not inherit from BaseException # is not allowed. class NonBaseException(object): pass diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index a916e878b7a..841cac9171c 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -617,7 +617,7 @@ class C: with self.assertRaisesRegex(TypeError, r'C\(\).__init__\(\) takes no arguments'): object.__init__(C(), 42) - # Class with both `__init__` & `__new__` method overriden + # Class with both `__init__` & `__new__` method overridden class D: def __new__(cls, *args, **kwargs): super().__new__(cls, *args, **kwargs) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 7e106affbe0..6c466f41e68 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -558,7 +558,7 @@ def __await__(self): c = new_coro() self.assertIsInstance(c, Awaitable) - c.close() # awoid RuntimeWarning that coro() was not awaited + c.close() # avoid RuntimeWarning that coro() was not awaited class CoroLike: pass Coroutine.register(CoroLike) @@ -608,7 +608,7 @@ def __await__(self): c = new_coro() self.assertIsInstance(c, Coroutine) - c.close() # awoid RuntimeWarning that coro() was not awaited + c.close() # avoid RuntimeWarning that coro() was not awaited class CoroLike: def send(self, value): @@ -1615,7 +1615,7 @@ def test_MutableSequence(self): '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert') def test_MutableSequence_mixins(self): - # Test the mixins of MutableSequence by creating a miminal concrete + # Test the mixins of MutableSequence by creating a minimal concrete # class inherited from it. class MutableSequenceSubclass(MutableSequence): def __init__(self): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 9d08a2d4c91..18ca202ca74 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -998,7 +998,7 @@ def __post_init__(self): self.assertEqual(C().x, 0) self.assertEqual(C(2).x, 4) - # Make sure that if we'r frozen, post-init can't set + # Make sure that if we're frozen, post-init can't set # attributes. @dataclass(frozen=True) class C: diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 35ec2e2f481..2245b974339 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -420,7 +420,7 @@ def __str__(self): p.keywords[self] = ['sth2'] return 'astr' - # Raplacing the value during key formatting should keep the original + # Replacing the value during key formatting should keep the original # value alive (at least long enough). p.keywords[MutatesYourDict()] = ['sth'] r = repr(p) diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index f88c762581d..bd17ad4a21b 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1458,7 +1458,7 @@ def remove_from_successors(i0, len=len): # If we create a square with one exit, we must visit it next; # else somebody else will have to visit it, and since there's # only one adjacent, there won't be a way to leave it again. - # Finelly, if we create more than one free square with a + # Finally, if we create more than one free square with a # single exit, we can only move to one of them next, leaving # the other one a dead end. ne0 = ne1 = 0 diff --git a/Lib/test/test_importlib/builtin/test_finder.py b/Lib/test/test_importlib/builtin/test_finder.py index a2e6e1edc36..084f3de6b65 100644 --- a/Lib/test/test_importlib/builtin/test_finder.py +++ b/Lib/test/test_importlib/builtin/test_finder.py @@ -22,7 +22,7 @@ def test_module(self): # Built-in modules cannot be a package. test_package = None - # Built-in modules cannobt be in a package. + # Built-in modules cannot be in a package. test_module_in_package = None # Built-in modules cannot be a package. diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py index 643a02c9ad6..cc80f26357e 100644 --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -267,7 +267,7 @@ def test_checked_hash_based_pyc(self): ) @util.writes_bytecode_files - def test_overriden_checked_hash_based_pyc(self): + def test_overridden_checked_hash_based_pyc(self): with util.create_modules('_temp') as mapping, \ unittest.mock.patch('_imp.check_hash_based_pycs', 'never'): source = mapping['_temp'] diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 13a86b12dd3..5b5bc650d2f 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1569,7 +1569,7 @@ class Foo(object): foo.__dict__['d'] = 1 self.assertEqual(inspect.getattr_static(foo, 'd'), 1) - # if the descriptor is a data-desciptor we should return the + # if the descriptor is a data-descriptor we should return the # descriptor descriptor.__set__ = lambda s, i, v: None self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 66748317b5f..9bfe4b0bc6e 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -579,7 +579,7 @@ def test_raw_bytes_io(self): self.read_ops(f, True) def test_large_file_ops(self): - # On Windows and Mac OSX this test comsumes large resources; It takes + # On Windows and Mac OSX this test consumes large resources; It takes # a long time to build the >2 GiB file and takes >2 GiB of disk space # therefore the resource must be enabled to run this test. if sys.platform[:3] == 'win' or sys.platform == 'darwin': diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py index f409c5b5110..21296ccafe5 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -141,7 +141,7 @@ def setUpModule(): except (ImportError, AttributeError): pass - # On Windows and Mac OSX this test comsumes large resources; It + # On Windows and Mac OSX this test consumes large resources; It # takes a long time to build the >2 GiB file and takes >2 GiB of disk # space therefore the resource must be enabled to run this test. # If not, nothing after this line stanza will be executed. diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 7101e3b1576..54049d2fb36 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -178,7 +178,7 @@ class BuiltinLevelsTest(BaseTest): """Test builtin levels and their inheritance.""" def test_flat(self): - #Logging levels in a flat logger namespace. + # Logging levels in a flat logger namespace. m = self.next_message ERR = logging.getLogger("ERR") @@ -248,7 +248,7 @@ def test_nested_explicit(self): ]) def test_nested_inherited(self): - #Logging levels in a nested namespace, inherited from parent loggers. + # Logging levels in a nested namespace, inherited from parent loggers. m = self.next_message INF = logging.getLogger("INF") @@ -1913,9 +1913,9 @@ def test_encoding_plain_file(self): def test_encoding_cyrillic_unicode(self): log = logging.getLogger("test") - #Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye) + # Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye) message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f' - #Ensure it's written in a Cyrillic encoding + # Ensure it's written in a Cyrillic encoding writer_class = codecs.getwriter('cp1251') writer_class.encoding = 'cp1251' stream = io.BytesIO() @@ -1929,7 +1929,7 @@ def test_encoding_cyrillic_unicode(self): handler.close() # check we wrote exactly those bytes, ignoring trailing \n etc s = stream.getvalue() - #Compare against what the data should be when encoded in CP-1251 + # Compare against what the data should be when encoded in CP-1251 self.assertEqual(s, b'\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n') @@ -1950,7 +1950,7 @@ def test_warnings(self): h.close() self.assertGreater(s.find("UserWarning: I'm warning you...\n"), 0) - #See if an explicit file uses the original implementation + # See if an explicit file uses the original implementation a_file = io.StringIO() warnings.showwarning("Explicit", UserWarning, "dummy.py", 42, a_file, "Dummy line") @@ -2091,7 +2091,7 @@ class ConfigDictTest(BaseTest): }, } - #As config1 but with a misspelt level on a handler + # As config1 but with a misspelt level on a handler config2a = { 'version': 1, 'formatters': { @@ -2119,7 +2119,7 @@ class ConfigDictTest(BaseTest): } - #As config1 but with a misspelt level on a logger + # As config1 but with a misspelt level on a logger config2b = { 'version': 1, 'formatters': { @@ -2286,8 +2286,8 @@ class ConfigDictTest(BaseTest): }, } - #config 7 does not define compiler.parser but defines compiler.lexer - #so compiler.parser should be disabled after applying it + # config 7 does not define compiler.parser but defines compiler.lexer + # so compiler.parser should be disabled after applying it config7 = { 'version': 1, 'formatters': { @@ -2432,7 +2432,7 @@ class ConfigDictTest(BaseTest): }, } - #As config1 but with a filter added + # As config1 but with a filter added config10 = { 'version': 1, 'formatters': { @@ -2466,7 +2466,7 @@ class ConfigDictTest(BaseTest): }, } - #As config1 but using cfg:// references + # As config1 but using cfg:// references config11 = { 'version': 1, 'true_formatters': { @@ -2497,7 +2497,7 @@ class ConfigDictTest(BaseTest): }, } - #As config11 but missing the version key + # As config11 but missing the version key config12 = { 'true_formatters': { 'form1' : { @@ -2527,7 +2527,7 @@ class ConfigDictTest(BaseTest): }, } - #As config11 but using an unsupported version + # As config11 but using an unsupported version config13 = { 'version': 2, 'true_formatters': { @@ -2728,7 +2728,7 @@ def test_config7_ok(self): # Original logger output is empty. self.assert_log_lines([]) - #Same as test_config_7_ok but don't disable old loggers. + # Same as test_config_7_ok but don't disable old loggers. def test_config_8_ok(self): with support.captured_stdout() as output: self.apply_config(self.config1) @@ -2809,15 +2809,15 @@ def test_config_9_ok(self): with support.captured_stdout() as output: self.apply_config(self.config9) logger = logging.getLogger("compiler.parser") - #Nothing will be output since both handler and logger are set to WARNING + # Nothing will be output since both handler and logger are set to WARNING logger.info(self.next_message()) self.assert_log_lines([], stream=output) self.apply_config(self.config9a) - #Nothing will be output since both handler is still set to WARNING + # Nothing will be output since handler is still set to WARNING logger.info(self.next_message()) self.assert_log_lines([], stream=output) self.apply_config(self.config9b) - #Message should now be output + # Message should now be output logger.info(self.next_message()) self.assert_log_lines([ ('INFO', '3'), @@ -2829,13 +2829,13 @@ def test_config_10_ok(self): logger = logging.getLogger("compiler.parser") logger.warning(self.next_message()) logger = logging.getLogger('compiler') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger('compiler.lexer') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger("compiler.parser.codegen") - #Output, as not filtered + # Output, as not filtered logger.error(self.next_message()) self.assert_log_lines([ ('WARNING', '1'), @@ -2894,13 +2894,13 @@ def test_listen_config_10_ok(self): logger = logging.getLogger("compiler.parser") logger.warning(self.next_message()) logger = logging.getLogger('compiler') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger('compiler.lexer') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger("compiler.parser.codegen") - #Output, as not filtered + # Output, as not filtered logger.error(self.next_message()) self.assert_log_lines([ ('WARNING', '1'), @@ -4335,7 +4335,7 @@ def test_rollover(self): break msg = 'No rotated files found, went back %d seconds' % GO_BACK if not found: - #print additional diagnostics + # print additional diagnostics dn, fn = os.path.split(self.fn) files = [f for f in os.listdir(dn) if f.startswith(fn)] print('Test time: %s' % now.strftime("%Y-%m-%d %H-%M-%S"), file=sys.stderr) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 70cb57465f5..44785d3e49a 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1423,7 +1423,7 @@ def assertIsNaN(self, value): class IsCloseTests(unittest.TestCase): - isclose = math.isclose # sublcasses should override this + isclose = math.isclose # subclasses should override this def assertIsClose(self, a, b, *args, **kwargs): self.assertTrue(self.isclose(a, b, *args, **kwargs), diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 647d391c798..2f1b2197809 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -30,7 +30,7 @@ def check_expr(self, s): self.roundtrip(parser.expr, s) def test_flags_passed(self): - # The unicode literals flags has to be passed from the paser to AST + # The unicode literals flags has to be passed from the parser to AST # generation. suite = parser.suite("from __future__ import unicode_literals; x = ''") code = suite.compile() diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index e2db72330c5..468c4a467e5 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -24,7 +24,7 @@ def test_autoseed(self): self.gen.seed() state1 = self.gen.getstate() time.sleep(0.1) - self.gen.seed() # diffent seeds at different times + self.gen.seed() # different seeds at different times state2 = self.gen.getstate() self.assertNotEqual(state1, state2) diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 99e7b4f8402..266adf01e04 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -274,7 +274,7 @@ def test_getsitepackages(self): 'site-packages') self.assertEqual(dirs[1], wanted) elif os.sep == '/': - # OS X non-framwework builds, Linux, FreeBSD, etc + # OS X non-framework builds, Linux, FreeBSD, etc self.assertEqual(len(dirs), 1) wanted = os.path.join('xoxo', 'lib', 'python%d.%d' % sys.version_info[:2], diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index b97a7688a60..5b4c5f9f8ca 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1444,7 +1444,7 @@ def test_idna(self): socket.gethostbyname(domain) socket.gethostbyname_ex(domain) socket.getaddrinfo(domain,0,socket.AF_UNSPEC,socket.SOCK_STREAM) - # this may not work if the forward lookup choses the IPv6 address, as that doesn't + # this may not work if the forward lookup chooses the IPv6 address, as that doesn't # have a reverse entry yet # socket.gethostbyaddr('?????????.python.org') @@ -4399,7 +4399,7 @@ def _testSmallReadNonBlocking(self): self.write_file.write(self.write_msg) self.write_file.flush() self.evt2.set() - # Avoid cloding the socket before the server test has finished, + # Avoid closing the socket before the server test has finished, # otherwise system recv() will return 0 instead of EWOULDBLOCK. self.serv_finished.wait(5.0) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index c65290b945f..98d3e571b73 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -850,7 +850,7 @@ def test_cert_time_to_seconds(self): self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901) self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds - # no special treatement for the special value: + # no special treatment for the special value: # 99991231235959Z (rfc 5280) self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index ed9e6d4f492..51dd9d95b2d 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -16,7 +16,7 @@ def basic(): # Many of the tests below are tricky because they involve pass statements. # If there is implicit control flow around a pass statement (in an except -# clause or else caluse) under what conditions do you set a line number +# clause or else clause) under what conditions do you set a line number # following that clause? diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 02812f32bc9..f2e3f8d8b22 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -2332,7 +2332,7 @@ def test_basic(self): sourcefile = serialize(doc, to_string=False) self.assertEqual(next(ET.iterparse(sourcefile))[0], 'end') - # With an explitit parser too (issue #9708) + # With an explicit parser too (issue #9708) sourcefile = serialize(doc, to_string=False) parser = ET.XMLParser(target=ET.TreeBuilder()) self.assertEqual(next(ET.iterparse(sourcefile, parser=parser))[0], diff --git a/Lib/test/test_zipapp.py b/Lib/test/test_zipapp.py index 948833b2006..73bddc79c17 100644 --- a/Lib/test/test_zipapp.py +++ b/Lib/test/test_zipapp.py @@ -365,7 +365,7 @@ def test_cmdline_copy_inplace(self): args = [str(original), '-o', str(original)] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a non-zero returm code. + # Program should exit with a non-zero return code. self.assertTrue(cm.exception.code) def test_cmdline_copy_change_main(self): @@ -375,7 +375,7 @@ def test_cmdline_copy_change_main(self): args = [str(original), '-o', str(target), '-m', 'foo:bar'] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a non-zero returm code. + # Program should exit with a non-zero return code. self.assertTrue(cm.exception.code) @patch('sys.stdout', new_callable=io.StringIO) @@ -385,7 +385,7 @@ def test_info_command(self, mock_stdout): args = [str(target), '--info'] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a zero returm code. + # Program should exit with a zero return code. self.assertEqual(cm.exception.code, 0) self.assertEqual(mock_stdout.getvalue(), "Interpreter: \n") @@ -395,7 +395,7 @@ def test_info_error(self): args = [str(target), '--info'] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a non-zero returm code. + # Program should exit with a non-zero return code. self.assertTrue(cm.exception.code) diff --git a/Lib/tkinter/test/test_ttk/test_functions.py b/Lib/tkinter/test/test_ttk/test_functions.py index a1b7cdfcd14..f8e69a9f416 100644 --- a/Lib/tkinter/test/test_ttk/test_functions.py +++ b/Lib/tkinter/test/test_ttk/test_functions.py @@ -149,7 +149,7 @@ def test_format_mapdict(self): # but when passing a single state, it can be anything valid = {'opt': [[1, 'value']]} self.assertEqual(ttk._format_mapdict(valid), ('-opt', '1 value')) - # special attention to single states which evalute to False + # special attention to single states which evaluate to False for stateval in (None, 0, False, '', set()): # just some samples valid = {'opt': [(stateval, 'value')]} self.assertEqual(ttk._format_mapdict(valid), @@ -251,7 +251,7 @@ def sample_expected(indent=0, indent_size=2): self.assertEqual(ttk._format_layoutlist([])[0], '') # _format_layoutlist always expects the second item (in every item) - # to act like a dict (except when the value evalutes to False). + # to act like a dict (except when the value evaluates to False). self.assertRaises(AttributeError, ttk._format_layoutlist, [('a', 'b')]) diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index 05c7364d203..e6c90cef7bb 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -83,7 +83,7 @@ def _mapdict_values(items): # ['active selected', 'grey', 'focus', [1, 2, 3, 4]] opt_val = [] for *state, val in items: - # hacks for bakward compatibility + # hacks for backward compatibility state[0] # raise IndexError if empty if len(state) == 1: # if it is empty (something that evaluates to False), then diff --git a/Lib/turtledemo/__main__.py b/Lib/turtledemo/__main__.py index 6daf694427d..17fe9a75e1c 100644 --- a/Lib/turtledemo/__main__.py +++ b/Lib/turtledemo/__main__.py @@ -259,7 +259,7 @@ def increase_size(self, dummy=None): return 'break' def update_mousewheel(self, event): - # For wheel up, event.delte = 120 on Windows, -1 on darwin. + # For wheel up, event.delta = 120 on Windows, -1 on darwin. # X-11 sends Control-Button-4 event instead. if (event.delta < 0) == (not darwin): return self.decrease_size() diff --git a/Lib/unittest/test/testmock/testmagicmethods.py b/Lib/unittest/test/testmock/testmagicmethods.py index 7993db33893..37623dcebc6 100644 --- a/Lib/unittest/test/testmock/testmagicmethods.py +++ b/Lib/unittest/test/testmock/testmagicmethods.py @@ -450,7 +450,7 @@ def test_divmod_and_rdivmod(self): self.assertIsInstance(bar_direct, MagicMock) # http://bugs.python.org/issue23310 - # Check if you can change behaviour of magic methds in MagicMock init + # Check if you can change behaviour of magic methods in MagicMock init def test_magic_in_initialization(self): m = MagicMock(**{'__str__.return_value': "12"}) self.assertEqual(str(m), "12") diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 7caef553efb..87277045b52 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -1062,7 +1062,7 @@ def _escape_cdata(text): # escape character data try: # it's worth avoiding do-nothing calls for strings that are - # shorter than 500 character, or so. assume that's, by far, + # shorter than 500 characters, or so. assume that's, by far, # the most common case in most applications. if "&" in text: text = text.replace("&", "&") diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index 28525036c46..1e8bb5f1bb9 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -1127,7 +1127,7 @@ class Transport: accept_gzip_encoding = True # if positive, encode request using gzip if it exceeds this threshold - # note that many server will get confused, so only use it if you know + # note that many servers will get confused, so only use it if you know # that they can decode such a request encode_threshold = None #None = don't encode @@ -1258,7 +1258,7 @@ def close(self): # Send HTTP request. # # @param host Host descriptor (URL or (URL, x509 info) tuple). - # @param handler Targer RPC handler (a path relative to host) + # @param handler Target RPC handler (a path relative to host) # @param request_body The XML-RPC request body # @param debug Enable debugging if debug is true. # @return An HTTPConnection. diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index cc6241f817a..bff4eae31b4 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1081,7 +1081,7 @@ def buildLibraries(): def buildPythonDocs(): # This stores the documentation as Resources/English.lproj/Documentation - # inside the framwork. pydoc and IDLE will pick it up there. + # inside the framework. pydoc and IDLE will pick it up there. print("Install python documentation") rootDir = os.path.join(WORKDIR, '_root') buildDir = os.path.join('../../Doc') diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index baa2e917706..f1da9f7a839 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1040,7 +1040,7 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args) } /* wait until the thread completes: it will never occur, since Py_FatalError() - exits the process immedialty. */ + exits the process immediately. */ PyThread_acquire_lock(lock, WAIT_LOCK); PyThread_release_lock(lock); PyThread_free_lock(lock); diff --git a/Tools/c-globals/check-c-globals.py b/Tools/c-globals/check-c-globals.py index 1de69a8751c..e68ed9271fe 100644 --- a/Tools/c-globals/check-c-globals.py +++ b/Tools/c-globals/check-c-globals.py @@ -135,7 +135,7 @@ def _is_exception(name): def _is_compiler(name): return ( - # Python/Pythyon-ast.c + # Python/Python-ast.c name.endswith('_type') or name.endswith('_singleton') or name.endswith('_attributes') diff --git a/setup.py b/setup.py index 09e35e50609..f1933f78dee 100644 --- a/setup.py +++ b/setup.py @@ -1399,7 +1399,7 @@ class db_found(Exception): pass if host_platform == 'darwin': # On OS X, there is no separate /usr/lib/libncursesw nor # libpanelw. If we are here, we found a locally-supplied - # version of libncursesw. There should be also be a + # version of libncursesw. There should also be a # libpanelw. _XOPEN_SOURCE defines are usually excluded # for OS X but we need _XOPEN_SOURCE_EXTENDED here for # ncurses wide char support From webhook-mailer at python.org Thu Dec 14 06:05:29 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 14 Dec 2017 11:05:29 -0000 Subject: [Python-checkins] bpo-32030: Add _PyMainInterpreterConfig.warnoptions (#4855) Message-ID: https://github.com/python/cpython/commit/374c6e178a7599aae46c857b17c6c8bc19dfe4c2 commit: 374c6e178a7599aae46c857b17c6c8bc19dfe4c2 branch: master author: Victor Stinner committer: GitHub date: 2017-12-14T12:05:26+01:00 summary: bpo-32030: Add _PyMainInterpreterConfig.warnoptions (#4855) Add warnoptions and xoptions fields to _PyMainInterpreterConfig. files: M Include/pystate.h M Modules/main.c M Python/pylifecycle.c diff --git a/Include/pystate.h b/Include/pystate.h index 9a26cc3909f..e8cf4134a8c 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -59,6 +59,8 @@ typedef struct { int install_signal_handlers; PyObject *argv; /* sys.argv list, can be NULL */ PyObject *module_search_path; /* sys.path list */ + PyObject *warnoptions; /* sys.warnoptions list, can be NULL */ + PyObject *xoptions; /* sys._xoptions dict, can be NULL */ } _PyMainInterpreterConfig; #define _PyMainInterpreterConfig_INIT \ diff --git a/Modules/main.c b/Modules/main.c index 3f942fe067a..6db7e5f7088 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -752,29 +752,67 @@ pymain_parse_cmdline_impl(_PyMain *pymain) static int -pymain_add_xoptions(_PyMain *pymain) +pymain_add_xoption(PyObject *opts, const wchar_t *s) +{ + PyObject *name, *value; + + const wchar_t *name_end = wcschr(s, L'='); + if (!name_end) { + name = PyUnicode_FromWideChar(s, -1); + value = Py_True; + Py_INCREF(value); + } + else { + name = PyUnicode_FromWideChar(s, name_end - s); + value = PyUnicode_FromWideChar(name_end + 1, -1); + } + if (name == NULL || value == NULL) { + goto error; + } + if (PyDict_SetItem(opts, name, value) < 0) { + goto error; + } + Py_DECREF(name); + Py_DECREF(value); + return 0; + +error: + Py_XDECREF(name); + Py_XDECREF(value); + return -1; +} + +static int +pymain_init_xoptions_dict(_PyMain *pymain) { _Py_OptList *options = &pymain->cmdline.xoptions; + PyObject *dict = PyDict_New(); + if (dict == NULL) { + return -1; + } + for (size_t i=0; i < options->len; i++) { wchar_t *option = options->options[i]; - if (_PySys_AddXOptionWithError(option) < 0) { - pymain->err = _Py_INIT_NO_MEMORY(); + if (pymain_add_xoption(dict, option) < 0) { + Py_DECREF(dict); return -1; } } + + pymain->config.xoptions = dict; return 0; } static int -pymain_add_warnings_optlist(_Py_OptList *warnings) +pymain_add_warnings_optlist(PyObject *warnoptions, _Py_OptList *warnings) { for (size_t i = 0; i < warnings->len; i++) { PyObject *option = PyUnicode_FromWideChar(warnings->options[i], -1); if (option == NULL) { return -1; } - if (_PySys_AddWarnOptionWithError(option)) { + if (PyList_Append(warnoptions, option)) { Py_DECREF(option); return -1; } @@ -785,14 +823,14 @@ pymain_add_warnings_optlist(_Py_OptList *warnings) static int -pymain_add_warning_dev_mode(_PyCoreConfig *core_config) +pymain_add_warning_dev_mode(PyObject *warnoptions, _PyCoreConfig *core_config) { if (core_config->dev_mode) { PyObject *option = PyUnicode_FromString("default"); if (option == NULL) { return -1; } - if (_PySys_AddWarnOptionWithError(option)) { + if (PyList_Append(warnoptions, option)) { Py_DECREF(option); return -1; } @@ -803,33 +841,38 @@ pymain_add_warning_dev_mode(_PyCoreConfig *core_config) static int -pymain_add_warning_bytes_flag(int bytes_warning_flag) +pymain_add_warning_bytes_flag(PyObject *warnoptions, int bytes_warning_flag) { /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c * don't even try to emit a warning, so we skip setting the filter in that * case. */ - if (bytes_warning_flag) { - const char *filter = (bytes_warning_flag > 1) ? "error::BytesWarning": - "default::BytesWarning"; - PyObject *option = PyUnicode_FromString(filter); - if (option == NULL) { - return -1; - } - if (_PySys_AddWarnOptionWithError(option)) { - Py_DECREF(option); - return -1; - } + if (!bytes_warning_flag) { + return 0; + } + + const char *filter = (bytes_warning_flag > 1) ? "error::BytesWarning": + "default::BytesWarning"; + PyObject *option = PyUnicode_FromString(filter); + if (option == NULL) { + return -1; + } + if (PyList_Append(warnoptions, option)) { Py_DECREF(option); + return -1; } + Py_DECREF(option); return 0; } static int -pymain_add_warnings_options(_PyMain *pymain) +pymain_init_warnoptions(_PyMain *pymain) { - PySys_ResetWarnOptions(); + PyObject *warnoptions = PyList_New(0); + if (warnoptions == NULL) { + return -1; + } /* The priority order for warnings configuration is (highest precedence * first): @@ -846,23 +889,25 @@ pymain_add_warnings_options(_PyMain *pymain) * the lowest precedence entries first so that later entries override them. */ - if (pymain_add_warning_dev_mode(&pymain->core_config) < 0) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + if (pymain_add_warning_dev_mode(warnoptions, &pymain->core_config) < 0) { + goto error; } - if (pymain_add_warnings_optlist(&pymain->env_warning_options) < 0) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + if (pymain_add_warnings_optlist(warnoptions, &pymain->env_warning_options) < 0) { + goto error; } - if (pymain_add_warnings_optlist(&pymain->cmdline.warning_options) < 0) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.warning_options) < 0) { + goto error; } - if (pymain_add_warning_bytes_flag(pymain->cmdline.bytes_warning) < 0) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + if (pymain_add_warning_bytes_flag(warnoptions, pymain->cmdline.bytes_warning) < 0) { + goto error; } + + pymain->config.warnoptions = warnoptions; return 0; + +error: + Py_DECREF(warnoptions); + return -1; } @@ -1092,7 +1137,7 @@ pymain_header(_PyMain *pymain) static int -pymain_create_argv_list(_PyMain *pymain) +pymain_init_argv(_PyMain *pymain) { int argc = pymain->sys_argc; wchar_t** argv = pymain->sys_argv; @@ -1918,7 +1963,6 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *c return err; } } - return _Py_INIT_OK(); } @@ -1941,15 +1985,15 @@ pymain_init_python_core(_PyMain *pymain) static int pymain_init_python_main(_PyMain *pymain) { - if (pymain_add_xoptions(pymain)) { + if (pymain_init_xoptions_dict(pymain)) { + pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - if (pymain_add_warnings_options(pymain)) { + if (pymain_init_warnoptions(pymain)) { + pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - - /* Create sys.argv list */ - if (pymain_create_argv_list(pymain) < 0) { + if (pymain_init_argv(pymain) < 0) { pymain->err = _Py_INIT_ERR("failed to create sys.argv"); return -1; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 31965f503ca..d813ddd6715 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -830,6 +830,8 @@ _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) { Py_CLEAR(config->argv); Py_CLEAR(config->module_search_path); + Py_CLEAR(config->warnoptions); + Py_CLEAR(config->xoptions); } @@ -883,10 +885,26 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return _Py_INIT_ERR("can't initialize time"); } + /* Set sys attributes */ assert(interp->config.module_search_path != NULL); if (PySys_SetObject("path", interp->config.module_search_path) != 0) { return _Py_INIT_ERR("can't assign sys.path"); } + if (interp->config.argv != NULL) { + if (PySys_SetObject("argv", interp->config.argv) != 0) { + return _Py_INIT_ERR("can't assign sys.argv"); + } + } + if (interp->config.warnoptions != NULL) { + if (PySys_SetObject("warnoptions", interp->config.warnoptions)) { + return _Py_INIT_ERR("can't assign sys.warnoptions"); + } + } + if (interp->config.xoptions != NULL) { + if (PySys_SetObject("_xoptions", interp->config.xoptions)) { + return _Py_INIT_ERR("can't assign sys._xoptions"); + } + } if (_PySys_EndInit(interp->sysdict) < 0) return _Py_INIT_ERR("can't finish initializing sys"); @@ -945,13 +963,6 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return err; } } - - if (interp->config.argv != NULL) { - if (PySys_SetObject("argv", interp->config.argv) != 0) { - return _Py_INIT_ERR("can't assign sys.argv"); - } - } - return _Py_INIT_OK(); } From webhook-mailer at python.org Thu Dec 14 08:18:29 2017 From: webhook-mailer at python.org (INADA Naoki) Date: Thu, 14 Dec 2017 13:18:29 -0000 Subject: [Python-checkins] bpo-29469: Remove unnecessary peephole optimizer (GH-4863) Message-ID: https://github.com/python/cpython/commit/eadad1b97f64619bfd246b9d3b60d25f456e0592 commit: eadad1b97f64619bfd246b9d3b60d25f456e0592 branch: master author: INADA Naoki committer: GitHub date: 2017-12-14T22:18:26+09:00 summary: bpo-29469: Remove unnecessary peephole optimizer (GH-4863) Conversions like `not a is b -> a is not b` are implemented in AST optimizer in previous commit (7ea143a). So this commit removes them from peephole optimizer. files: M Python/peephole.c diff --git a/Python/peephole.c b/Python/peephole.c index 3c5290fadc0..58171465633 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -345,21 +345,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, in_consts = 0; switch (opcode) { - /* not a is b --> a is not b - not a in b --> a not in b - not a is not b --> a is b - not a not in b --> a in b - */ - case COMPARE_OP: - j = get_arg(codestr, i); - if (j < 6 || j > 9 || - nextop != UNARY_NOT || - !ISBASICBLOCK(blocks, op_start, i + 1)) - break; - codestr[i] = PACKOPARG(opcode, j^1); - fill_nops(codestr, i + 1, nexti + 1); - break; - /* Skip over LOAD_CONST trueconst POP_JUMP_IF_FALSE xx. This improves "while 1" performance. */ From webhook-mailer at python.org Thu Dec 14 09:19:56 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 14 Dec 2017 14:19:56 -0000 Subject: [Python-checkins] [3.6] bpo-32297: Fix misspellings in Python source code comments (GH-4803) (#4864) Message-ID: https://github.com/python/cpython/commit/28453feaa8d88bbcbf6d834b1d5ca396d17265f2 commit: 28453feaa8d88bbcbf6d834b1d5ca396d17265f2 branch: 3.6 author: Andrew Svetlov committer: GitHub date: 2017-12-14T16:19:51+02:00 summary: [3.6] bpo-32297: Fix misspellings in Python source code comments (GH-4803) (#4864) * [3.6] bpo-32297: Few misspellings found in Python source code comments. (GH-4803) * Fix multiple typos in code comments * Add spacing in comments (test_logging.py, test_math.py) * Fix spaces at the beginning of comments in test_logging.py. (cherry picked from commit 53f7a7c2814fbfd8a29200926601a32fa48bacb3) files: M Doc/includes/email-read-alternative.py M Lib/ctypes/test/test_pep3118.py M Lib/ctypes/test/test_structures.py M Lib/email/quoprimime.py M Lib/http/client.py M Lib/os.py M Lib/tarfile.py M Lib/test/_test_multiprocessing.py M Lib/test/test_baseexception.py M Lib/test/test_class.py M Lib/test/test_collections.py M Lib/test/test_functools.py M Lib/test/test_generators.py M Lib/test/test_importlib/builtin/test_finder.py M Lib/test/test_inspect.py M Lib/test/test_io.py M Lib/test/test_largefile.py M Lib/test/test_logging.py M Lib/test/test_math.py M Lib/test/test_parser.py M Lib/test/test_random.py M Lib/test/test_site.py M Lib/test/test_socket.py M Lib/test/test_ssl.py M Lib/test/test_sys_settrace.py M Lib/test/test_xml_etree.py M Lib/test/test_zipapp.py M Lib/tkinter/test/test_ttk/test_functions.py M Lib/tkinter/ttk.py M Lib/turtledemo/__main__.py M Lib/unittest/test/testmock/testmagicmethods.py M Lib/xml/etree/ElementTree.py M Lib/xmlrpc/client.py M Mac/BuildScript/build-installer.py M Modules/faulthandler.c M setup.py diff --git a/Doc/includes/email-read-alternative.py b/Doc/includes/email-read-alternative.py index 3f5ab24c0fb..5ea84e62584 100644 --- a/Doc/includes/email-read-alternative.py +++ b/Doc/includes/email-read-alternative.py @@ -21,7 +21,7 @@ print('From:', msg['from']) print('Subject:', msg['subject']) -# If we want to print a priview of the message content, we can extract whatever +# If we want to print a preview of the message content, we can extract whatever # the least formatted payload is and print the first three lines. Of course, # if the message has no plain text part printing the first three lines of html # is probably useless, but this is just a conceptual example. diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py index f3c0e23e53e..81e8ca7638f 100644 --- a/Lib/ctypes/test/test_pep3118.py +++ b/Lib/ctypes/test/test_pep3118.py @@ -188,7 +188,7 @@ class Complete(Structure): (PackedPoint, "B", (), PackedPoint), (Point2, "T{ integer diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 5d4c86ce366..631b69dcba4 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1056,7 +1056,7 @@ def frombuf(cls, buf, encoding, errors): # The old GNU sparse format occupies some of the unused # space in the buffer for up to 4 sparse structures. - # Save the them for later processing in _proc_sparse(). + # Save them for later processing in _proc_sparse(). if obj.type == GNUTYPE_SPARSE: pos = 386 structs = [] diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index f01c0041d65..774e797f02e 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3896,7 +3896,7 @@ def test_noforkbomb(self): # class TestForkAwareThreadLock(unittest.TestCase): - # We recurisvely start processes. Issue #17555 meant that the + # We recursively start processes. Issue #17555 meant that the # after fork registry would get duplicate entries for the same # lock. The size of the registry at generation n was ~2**n. diff --git a/Lib/test/test_baseexception.py b/Lib/test/test_baseexception.py index 27d514fe2ee..e7ce0b43456 100644 --- a/Lib/test/test_baseexception.py +++ b/Lib/test/test_baseexception.py @@ -163,7 +163,7 @@ def test_raise_string(self): self.raise_fails("spam") def test_catch_non_BaseException(self): - # Tryinng to catch an object that does not inherit from BaseException + # Trying to catch an object that does not inherit from BaseException # is not allowed. class NonBaseException(object): pass diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index ecc01f27795..507c723e718 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -595,5 +595,6 @@ class A: with self.assertRaises(TypeError): type.__setattr__(A, b'x', None) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 47f756213dd..cbb08dbdd75 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -550,7 +550,7 @@ def __await__(self): c = new_coro() self.assertIsInstance(c, Awaitable) - c.close() # awoid RuntimeWarning that coro() was not awaited + c.close() # avoid RuntimeWarning that coro() was not awaited class CoroLike: pass Coroutine.register(CoroLike) @@ -600,7 +600,7 @@ def __await__(self): c = new_coro() self.assertIsInstance(c, Coroutine) - c.close() # awoid RuntimeWarning that coro() was not awaited + c.close() # avoid RuntimeWarning that coro() was not awaited class CoroLike: def send(self, value): @@ -1607,7 +1607,7 @@ def test_MutableSequence(self): '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert') def test_MutableSequence_mixins(self): - # Test the mixins of MutableSequence by creating a miminal concrete + # Test the mixins of MutableSequence by creating a minimal concrete # class inherited from it. class MutableSequenceSubclass(MutableSequence): def __init__(self): diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index cd4664cec08..145440027c9 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -420,7 +420,7 @@ def __str__(self): p.keywords[self] = ['sth2'] return 'astr' - # Raplacing the value during key formatting should keep the original + # Replacing the value during key formatting should keep the original # value alive (at least long enough). p.keywords[MutatesYourDict()] = ['sth'] r = repr(p) diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 7107bd99932..b8d5bbe3b05 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1459,7 +1459,7 @@ def remove_from_successors(i0, len=len): # If we create a square with one exit, we must visit it next; # else somebody else will have to visit it, and since there's # only one adjacent, there won't be a way to leave it again. - # Finelly, if we create more than one free square with a + # Finally, if we create more than one free square with a # single exit, we can only move to one of them next, leaving # the other one a dead end. ne0 = ne1 = 0 diff --git a/Lib/test/test_importlib/builtin/test_finder.py b/Lib/test/test_importlib/builtin/test_finder.py index a2e6e1edc36..084f3de6b65 100644 --- a/Lib/test/test_importlib/builtin/test_finder.py +++ b/Lib/test/test_importlib/builtin/test_finder.py @@ -22,7 +22,7 @@ def test_module(self): # Built-in modules cannot be a package. test_package = None - # Built-in modules cannobt be in a package. + # Built-in modules cannot be in a package. test_module_in_package = None # Built-in modules cannot be a package. diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index bdad38643b9..55436748d6f 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1564,7 +1564,7 @@ class Foo(object): foo.__dict__['d'] = 1 self.assertEqual(inspect.getattr_static(foo, 'd'), 1) - # if the descriptor is a data-desciptor we should return the + # if the descriptor is a data-descriptor we should return the # descriptor descriptor.__set__ = lambda s, i, v: None self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index c81672325ba..42dbbd35dc9 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -568,8 +568,8 @@ def test_raw_bytes_io(self): self.read_ops(f, True) def test_large_file_ops(self): - # On Windows and Mac OSX this test comsumes large resources; It takes - # a long time to build the >2GB file and takes >2GB of disk space + # On Windows and Mac OSX this test consumes large resources; It takes + # a long time to build the >2 GiB file and takes >2 GiB of disk space # therefore the resource must be enabled to run this test. if sys.platform[:3] == 'win' or sys.platform == 'darwin': support.requires( diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py index 5b276e76ff2..d07bb8eee5a 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -141,8 +141,8 @@ def setUpModule(): except (ImportError, AttributeError): pass - # On Windows and Mac OSX this test comsumes large resources; It - # takes a long time to build the >2GB file and takes >2GB of disk + # On Windows and Mac OSX this test consumes large resources; It + # takes a long time to build the >2 GiB file and takes >2 GiB of disk # space therefore the resource must be enabled to run this test. # If not, nothing after this line stanza will be executed. if sys.platform[:3] == 'win' or sys.platform == 'darwin': diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index b325f7697f7..fc067138c3b 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -174,7 +174,7 @@ class BuiltinLevelsTest(BaseTest): """Test builtin levels and their inheritance.""" def test_flat(self): - #Logging levels in a flat logger namespace. + # Logging levels in a flat logger namespace. m = self.next_message ERR = logging.getLogger("ERR") @@ -244,7 +244,7 @@ def test_nested_explicit(self): ]) def test_nested_inherited(self): - #Logging levels in a nested namespace, inherited from parent loggers. + # Logging levels in a nested namespace, inherited from parent loggers. m = self.next_message INF = logging.getLogger("INF") @@ -1901,9 +1901,9 @@ def test_encoding_plain_file(self): def test_encoding_cyrillic_unicode(self): log = logging.getLogger("test") - #Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye) + # Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye) message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f' - #Ensure it's written in a Cyrillic encoding + # Ensure it's written in a Cyrillic encoding writer_class = codecs.getwriter('cp1251') writer_class.encoding = 'cp1251' stream = io.BytesIO() @@ -1917,7 +1917,7 @@ def test_encoding_cyrillic_unicode(self): handler.close() # check we wrote exactly those bytes, ignoring trailing \n etc s = stream.getvalue() - #Compare against what the data should be when encoded in CP-1251 + # Compare against what the data should be when encoded in CP-1251 self.assertEqual(s, b'\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n') @@ -1938,7 +1938,7 @@ def test_warnings(self): h.close() self.assertGreater(s.find("UserWarning: I'm warning you...\n"), 0) - #See if an explicit file uses the original implementation + # See if an explicit file uses the original implementation a_file = io.StringIO() warnings.showwarning("Explicit", UserWarning, "dummy.py", 42, a_file, "Dummy line") @@ -2079,7 +2079,7 @@ class ConfigDictTest(BaseTest): }, } - #As config1 but with a misspelt level on a handler + # As config1 but with a misspelt level on a handler config2a = { 'version': 1, 'formatters': { @@ -2107,7 +2107,7 @@ class ConfigDictTest(BaseTest): } - #As config1 but with a misspelt level on a logger + # As config1 but with a misspelt level on a logger config2b = { 'version': 1, 'formatters': { @@ -2274,8 +2274,8 @@ class ConfigDictTest(BaseTest): }, } - #config 7 does not define compiler.parser but defines compiler.lexer - #so compiler.parser should be disabled after applying it + # config 7 does not define compiler.parser but defines compiler.lexer + # so compiler.parser should be disabled after applying it config7 = { 'version': 1, 'formatters': { @@ -2420,7 +2420,7 @@ class ConfigDictTest(BaseTest): }, } - #As config1 but with a filter added + # As config1 but with a filter added config10 = { 'version': 1, 'formatters': { @@ -2454,7 +2454,7 @@ class ConfigDictTest(BaseTest): }, } - #As config1 but using cfg:// references + # As config1 but using cfg:// references config11 = { 'version': 1, 'true_formatters': { @@ -2485,7 +2485,7 @@ class ConfigDictTest(BaseTest): }, } - #As config11 but missing the version key + # As config11 but missing the version key config12 = { 'true_formatters': { 'form1' : { @@ -2515,7 +2515,7 @@ class ConfigDictTest(BaseTest): }, } - #As config11 but using an unsupported version + # As config11 but using an unsupported version config13 = { 'version': 2, 'true_formatters': { @@ -2716,7 +2716,7 @@ def test_config7_ok(self): # Original logger output is empty. self.assert_log_lines([]) - #Same as test_config_7_ok but don't disable old loggers. + # Same as test_config_7_ok but don't disable old loggers. def test_config_8_ok(self): with support.captured_stdout() as output: self.apply_config(self.config1) @@ -2797,15 +2797,15 @@ def test_config_9_ok(self): with support.captured_stdout() as output: self.apply_config(self.config9) logger = logging.getLogger("compiler.parser") - #Nothing will be output since both handler and logger are set to WARNING + # Nothing will be output since both handler and logger are set to WARNING logger.info(self.next_message()) self.assert_log_lines([], stream=output) self.apply_config(self.config9a) - #Nothing will be output since both handler is still set to WARNING + # Nothing will be output since handler is still set to WARNING logger.info(self.next_message()) self.assert_log_lines([], stream=output) self.apply_config(self.config9b) - #Message should now be output + # Message should now be output logger.info(self.next_message()) self.assert_log_lines([ ('INFO', '3'), @@ -2817,13 +2817,13 @@ def test_config_10_ok(self): logger = logging.getLogger("compiler.parser") logger.warning(self.next_message()) logger = logging.getLogger('compiler') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger('compiler.lexer') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger("compiler.parser.codegen") - #Output, as not filtered + # Output, as not filtered logger.error(self.next_message()) self.assert_log_lines([ ('WARNING', '1'), @@ -2884,13 +2884,13 @@ def test_listen_config_10_ok(self): logger = logging.getLogger("compiler.parser") logger.warning(self.next_message()) logger = logging.getLogger('compiler') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger('compiler.lexer') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger("compiler.parser.codegen") - #Output, as not filtered + # Output, as not filtered logger.error(self.next_message()) self.assert_log_lines([ ('WARNING', '1'), @@ -4244,7 +4244,7 @@ def test_rollover(self): break msg = 'No rotated files found, went back %d seconds' % GO_BACK if not found: - #print additional diagnostics + # print additional diagnostics dn, fn = os.path.split(self.fn) files = [f for f in os.listdir(dn) if f.startswith(fn)] print('Test time: %s' % now.strftime("%Y-%m-%d %H-%M-%S"), file=sys.stderr) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index eaa41bca3f6..e6e30802887 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1288,7 +1288,7 @@ def test_mtestfile(self): class IsCloseTests(unittest.TestCase): - isclose = math.isclose # sublcasses should override this + isclose = math.isclose # subclasses should override this def assertIsClose(self, a, b, *args, **kwargs): self.assertTrue(self.isclose(a, b, *args, **kwargs), diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 70cabb28598..4a3571df185 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -30,7 +30,7 @@ def check_expr(self, s): self.roundtrip(parser.expr, s) def test_flags_passed(self): - # The unicode literals flags has to be passed from the paser to AST + # The unicode literals flags has to be passed from the parser to AST # generation. suite = parser.suite("from __future__ import unicode_literals; x = ''") code = suite.compile() diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index b42bf2a7124..3e57a82b63e 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -22,7 +22,7 @@ def test_autoseed(self): self.gen.seed() state1 = self.gen.getstate() time.sleep(0.1) - self.gen.seed() # diffent seeds at different times + self.gen.seed() # different seeds at different times state2 = self.gen.getstate() self.assertNotEqual(state1, state2) diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 4029617aa1d..dce2aac909d 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -259,7 +259,7 @@ def test_getsitepackages(self): 'site-packages') self.assertEqual(dirs[1], wanted) elif os.sep == '/': - # OS X non-framwework builds, Linux, FreeBSD, etc + # OS X non-framework builds, Linux, FreeBSD, etc self.assertEqual(len(dirs), 1) wanted = os.path.join('xoxo', 'lib', 'python%d.%d' % sys.version_info[:2], diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index a79ebfe9a34..00237626d6c 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1357,7 +1357,7 @@ def test_idna(self): socket.gethostbyname(domain) socket.gethostbyname_ex(domain) socket.getaddrinfo(domain,0,socket.AF_UNSPEC,socket.SOCK_STREAM) - # this may not work if the forward lookup choses the IPv6 address, as that doesn't + # this may not work if the forward lookup chooses the IPv6 address, as that doesn't # have a reverse entry yet # socket.gethostbyaddr('?????????.python.org') @@ -4239,7 +4239,7 @@ def _testSmallReadNonBlocking(self): self.write_file.write(self.write_msg) self.write_file.flush() self.evt2.set() - # Avoid cloding the socket before the server test has finished, + # Avoid closing the socket before the server test has finished, # otherwise system recv() will return 0 instead of EWOULDBLOCK. self.serv_finished.wait(5.0) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 54644e1596c..daffaf7af87 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -829,7 +829,7 @@ def test_cert_time_to_seconds(self): self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901) self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds - # no special treatement for the special value: + # no special treatment for the special value: # 99991231235959Z (rfc 5280) self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 25c5835fd6f..ec537bee91c 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -16,7 +16,7 @@ def basic(): # Many of the tests below are tricky because they involve pass statements. # If there is implicit control flow around a pass statement (in an except -# clause or else caluse) under what conditions do you set a line number +# clause or else clause) under what conditions do you set a line number # following that clause? diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 7adfbdfd7a9..f8af69fa110 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -2280,7 +2280,7 @@ def test_basic(self): sourcefile = serialize(doc, to_string=False) self.assertEqual(next(ET.iterparse(sourcefile))[0], 'end') - # With an explitit parser too (issue #9708) + # With an explicit parser too (issue #9708) sourcefile = serialize(doc, to_string=False) parser = ET.XMLParser(target=ET.TreeBuilder()) self.assertEqual(next(ET.iterparse(sourcefile, parser=parser))[0], diff --git a/Lib/test/test_zipapp.py b/Lib/test/test_zipapp.py index d8d44375bdd..4607f57afc3 100644 --- a/Lib/test/test_zipapp.py +++ b/Lib/test/test_zipapp.py @@ -311,7 +311,7 @@ def test_cmdline_copy_inplace(self): args = [str(original), '-o', str(original)] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a non-zero returm code. + # Program should exit with a non-zero return code. self.assertTrue(cm.exception.code) def test_cmdline_copy_change_main(self): @@ -321,7 +321,7 @@ def test_cmdline_copy_change_main(self): args = [str(original), '-o', str(target), '-m', 'foo:bar'] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a non-zero returm code. + # Program should exit with a non-zero return code. self.assertTrue(cm.exception.code) @patch('sys.stdout', new_callable=io.StringIO) @@ -331,7 +331,7 @@ def test_info_command(self, mock_stdout): args = [str(target), '--info'] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a zero returm code. + # Program should exit with a zero return code. self.assertEqual(cm.exception.code, 0) self.assertEqual(mock_stdout.getvalue(), "Interpreter: \n") @@ -341,7 +341,7 @@ def test_info_error(self): args = [str(target), '--info'] with self.assertRaises(SystemExit) as cm: zipapp.main(args) - # Program should exit with a non-zero returm code. + # Program should exit with a non-zero return code. self.assertTrue(cm.exception.code) diff --git a/Lib/tkinter/test/test_ttk/test_functions.py b/Lib/tkinter/test/test_ttk/test_functions.py index a1b7cdfcd14..f8e69a9f416 100644 --- a/Lib/tkinter/test/test_ttk/test_functions.py +++ b/Lib/tkinter/test/test_ttk/test_functions.py @@ -149,7 +149,7 @@ def test_format_mapdict(self): # but when passing a single state, it can be anything valid = {'opt': [[1, 'value']]} self.assertEqual(ttk._format_mapdict(valid), ('-opt', '1 value')) - # special attention to single states which evalute to False + # special attention to single states which evaluate to False for stateval in (None, 0, False, '', set()): # just some samples valid = {'opt': [(stateval, 'value')]} self.assertEqual(ttk._format_mapdict(valid), @@ -251,7 +251,7 @@ def sample_expected(indent=0, indent_size=2): self.assertEqual(ttk._format_layoutlist([])[0], '') # _format_layoutlist always expects the second item (in every item) - # to act like a dict (except when the value evalutes to False). + # to act like a dict (except when the value evaluates to False). self.assertRaises(AttributeError, ttk._format_layoutlist, [('a', 'b')]) diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index 635b500579e..42e29bd3e5c 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -83,7 +83,7 @@ def _mapdict_values(items): # ['active selected', 'grey', 'focus', [1, 2, 3, 4]] opt_val = [] for *state, val in items: - # hacks for bakward compatibility + # hacks for backward compatibility state[0] # raise IndexError if empty if len(state) == 1: # if it is empty (something that evaluates to False), then diff --git a/Lib/turtledemo/__main__.py b/Lib/turtledemo/__main__.py index 6daf694427d..17fe9a75e1c 100644 --- a/Lib/turtledemo/__main__.py +++ b/Lib/turtledemo/__main__.py @@ -259,7 +259,7 @@ def increase_size(self, dummy=None): return 'break' def update_mousewheel(self, event): - # For wheel up, event.delte = 120 on Windows, -1 on darwin. + # For wheel up, event.delta = 120 on Windows, -1 on darwin. # X-11 sends Control-Button-4 event instead. if (event.delta < 0) == (not darwin): return self.decrease_size() diff --git a/Lib/unittest/test/testmock/testmagicmethods.py b/Lib/unittest/test/testmock/testmagicmethods.py index 24569b532de..4186c8e967c 100644 --- a/Lib/unittest/test/testmock/testmagicmethods.py +++ b/Lib/unittest/test/testmock/testmagicmethods.py @@ -450,7 +450,7 @@ def test_divmod_and_rdivmod(self): self.assertIsInstance(bar_direct, MagicMock) # http://bugs.python.org/issue23310 - # Check if you can change behaviour of magic methds in MagicMock init + # Check if you can change behaviour of magic methods in MagicMock init def test_magic_in_initialization(self): m = MagicMock(**{'__str__.return_value': "12"}) self.assertEqual(str(m), "12") diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 735405681ff..cf4e1da9766 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -1061,7 +1061,7 @@ def _escape_cdata(text): # escape character data try: # it's worth avoiding do-nothing calls for strings that are - # shorter than 500 character, or so. assume that's, by far, + # shorter than 500 characters, or so. assume that's, by far, # the most common case in most applications. if "&" in text: text = text.replace("&", "&") diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index bd3278e005a..88ee551f125 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -1127,7 +1127,7 @@ class Transport: accept_gzip_encoding = True # if positive, encode request using gzip if it exceeds this threshold - # note that many server will get confused, so only use it if you know + # note that many servers will get confused, so only use it if you know # that they can decode such a request encode_threshold = None #None = don't encode @@ -1258,7 +1258,7 @@ def close(self): # Send HTTP request. # # @param host Host descriptor (URL or (URL, x509 info) tuple). - # @param handler Targer RPC handler (a path relative to host) + # @param handler Target RPC handler (a path relative to host) # @param request_body The XML-RPC request body # @param debug Enable debugging if debug is true. # @return An HTTPConnection. diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 52f391a4316..ff02fb37126 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1080,7 +1080,7 @@ def buildLibraries(): def buildPythonDocs(): # This stores the documentation as Resources/English.lproj/Documentation - # inside the framwork. pydoc and IDLE will pick it up there. + # inside the framework. pydoc and IDLE will pick it up there. print("Install python documentation") rootDir = os.path.join(WORKDIR, '_root') buildDir = os.path.join('../../Doc') diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 92aa1d444bb..227424f8bba 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1036,7 +1036,7 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args) } /* wait until the thread completes: it will never occur, since Py_FatalError() - exits the process immedialty. */ + exits the process immediately. */ PyThread_acquire_lock(lock, WAIT_LOCK); PyThread_release_lock(lock); PyThread_free_lock(lock); diff --git a/setup.py b/setup.py index 0d644db8573..5e2b81bbb6b 100644 --- a/setup.py +++ b/setup.py @@ -1391,7 +1391,7 @@ class db_found(Exception): pass if host_platform == 'darwin': # On OS X, there is no separate /usr/lib/libncursesw nor # libpanelw. If we are here, we found a locally-supplied - # version of libncursesw. There should be also be a + # version of libncursesw. There should also be a # libpanelw. _XOPEN_SOURCE defines are usually excluded # for OS X but we need _XOPEN_SOURCE_EXTENDED here for # ncurses wide char support From webhook-mailer at python.org Thu Dec 14 09:41:11 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 14 Dec 2017 14:41:11 -0000 Subject: [Python-checkins] pythoninfo: sync with master (#4844) Message-ID: https://github.com/python/cpython/commit/4f37105277e9c3d86c44ad385ad0f5e9b7768a85 commit: 4f37105277e9c3d86c44ad385ad0f5e9b7768a85 branch: 3.6 author: Victor Stinner committer: GitHub date: 2017-12-14T15:41:06+01:00 summary: pythoninfo: sync with master (#4844) files: M Lib/test/pythoninfo.py diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index c238ef7b75c..9ca26c99708 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -1,5 +1,5 @@ """ -Collect various informations about Python to help debugging test failures. +Collect various information about Python to help debugging test failures. """ from __future__ import print_function import errno @@ -40,7 +40,7 @@ def add(self, key, value): def get_infos(self): """ - Get informations as a key:value dictionary where values are strings. + Get information as a key:value dictionary where values are strings. """ return {key: str(value) for key, value in self.info.items()} @@ -56,6 +56,14 @@ def copy_attributes(info_add, obj, name_fmt, attributes, *, formatter=None): info_add(name, value) +def copy_attr(info_add, name, mod, attr_name): + try: + value = getattr(mod, attr_name) + except AttributeError: + return + info_add(name, value) + + def call_func(info_add, name, mod, func_name, *, formatter=None): try: func = getattr(mod, func_name) @@ -143,6 +151,11 @@ def collect_locale(info_add): info_add('locale.encoding', locale.getpreferredencoding(False)) +def collect_builtins(info_add): + info_add('builtins.float.float_format', float.__getformat__("float")) + info_add('builtins.float.double_format', float.__getformat__("double")) + + def collect_os(info_add): import os @@ -162,17 +175,16 @@ def format_attr(attr, value): ) copy_attributes(info_add, os, 'os.%s', attributes, formatter=format_attr) - info_add("os.cwd", os.getcwd()) + call_func(info_add, 'os.cwd', os, 'getcwd') call_func(info_add, 'os.uid', os, 'getuid') call_func(info_add, 'os.gid', os, 'getgid') call_func(info_add, 'os.uname', os, 'uname') - if hasattr(os, 'getgroups'): - groups = os.getgroups() - groups = map(str, groups) - groups = ', '.join(groups) - info_add("os.groups", groups) + def format_groups(groups): + return ', '.join(map(str, groups)) + + call_func(info_add, 'os.groups', os, 'getgroups', formatter=format_groups) if hasattr(os, 'getlogin'): try: @@ -184,11 +196,7 @@ def format_attr(attr, value): else: info_add("os.login", login) - if hasattr(os, 'cpu_count'): - cpu_count = os.cpu_count() - if cpu_count: - info_add('os.cpu_count', cpu_count) - + call_func(info_add, 'os.cpu_count', os, 'cpu_count') call_func(info_add, 'os.loadavg', os, 'getloadavg') # Get environment variables: filter to list @@ -219,7 +227,9 @@ def format_attr(attr, value): ) for name, value in os.environ.items(): uname = name.upper() - if (uname in ENV_VARS or uname.startswith(("PYTHON", "LC_")) + if (uname in ENV_VARS + # Copy PYTHON* and LC_* variables + or uname.startswith(("PYTHON", "LC_")) # Visual Studio: VS140COMNTOOLS or (uname.startswith("VS") and uname.endswith("COMNTOOLS"))): info_add('os.environ[%s]' % name, value) @@ -313,12 +323,10 @@ def collect_time(info_add): ) copy_attributes(info_add, time, 'time.%s', attributes) - if not hasattr(time, 'get_clock_info'): - return - - for clock in ('time', 'perf_counter'): - tinfo = time.get_clock_info(clock) - info_add('time.%s' % clock, tinfo) + if hasattr(time, 'get_clock_info'): + for clock in ('time', 'perf_counter'): + tinfo = time.get_clock_info(clock) + info_add('time.%s' % clock, tinfo) def collect_sysconfig(info_add): @@ -331,7 +339,6 @@ def collect_sysconfig(info_add): 'CCSHARED', 'CFLAGS', 'CFLAGSFORSHARED', - 'PY_LDFLAGS', 'CONFIG_ARGS', 'HOST_GNU_TYPE', 'MACHDEP', @@ -339,6 +346,7 @@ def collect_sysconfig(info_add): 'OPT', 'PY_CFLAGS', 'PY_CFLAGS_NODIST', + 'PY_LDFLAGS', 'Py_DEBUG', 'Py_ENABLE_SHARED', 'SHELL', @@ -422,6 +430,54 @@ def collect_decimal(info_add): copy_attributes(info_add, _decimal, '_decimal.%s', attributes) +def collect_testcapi(info_add): + try: + import _testcapi + except ImportError: + return + + call_func(info_add, 'pymem.allocator', _testcapi, 'pymem_getallocatorsname') + copy_attr(info_add, 'pymem.with_pymalloc', _testcapi, 'WITH_PYMALLOC') + + +def collect_resource(info_add): + try: + import resource + except ImportError: + return + + limits = [attr for attr in dir(resource) if attr.startswith('RLIMIT_')] + for name in limits: + key = getattr(resource, name) + value = resource.getrlimit(key) + info_add('resource.%s' % name, value) + + +def collect_test_socket(info_add): + try: + from test import test_socket + except ImportError: + return + + # all check attributes like HAVE_SOCKET_CAN + attributes = [name for name in dir(test_socket) + if name.startswith('HAVE_')] + copy_attributes(info_add, test_socket, 'test_socket.%s', attributes) + + +def collect_test_support(info_add): + try: + from test import support + except ImportError: + return + + attributes = ('IPV6_ENABLED',) + copy_attributes(info_add, support, 'test_support.%s', attributes) + + call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available') + call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized') + + def collect_info(info): error = False info_add = info.add @@ -430,6 +486,7 @@ def collect_info(info): # collect_os() should be the first, to check the getrandom() status collect_os, + collect_builtins, collect_gdb, collect_locale, collect_platform, @@ -444,6 +501,12 @@ def collect_info(info): collect_zlib, collect_expat, collect_decimal, + collect_testcapi, + collect_resource, + + # Collecting from tests should be last as they have side effects. + collect_test_socket, + collect_test_support, ): try: collect_func(info_add) From webhook-mailer at python.org Thu Dec 14 09:42:24 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Thu, 14 Dec 2017 14:42:24 -0000 Subject: [Python-checkins] bpo-32314: Implement asyncio.run() (#4852) Message-ID: https://github.com/python/cpython/commit/02a0a19206da6902c3855a1fa09e60b208474cfa commit: 02a0a19206da6902c3855a1fa09e60b208474cfa branch: master author: Yury Selivanov committer: GitHub date: 2017-12-14T09:42:21-05:00 summary: bpo-32314: Implement asyncio.run() (#4852) files: A Lib/asyncio/runners.py A Lib/test/test_asyncio/test_runners.py A Misc/NEWS.d/next/Library/2017-12-13-16-47-38.bpo-32314.W4_U2j.rst M Doc/library/asyncio-task.rst M Lib/asyncio/__init__.py diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index a8a0a8e85ef..0d0569f0ba1 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -92,6 +92,24 @@ Coroutines (and tasks) can only run when the event loop is running. used in a callback-style code, wrap its result with :func:`ensure_future`. +.. function:: asyncio.run(coro, \*, debug=False) + + This function runs the passed coroutine, taking care of + managing the asyncio event loop and finalizing asynchronous + generators. + + This function cannot be called when another asyncio event loop is + running in the same thread. + + If debug is True, the event loop will be run in debug mode. + + This function always creates a new event loop and closes it at + the end. It should be used as a main entry point for asyncio + programs, and should ideally only be called once. + + .. versionadded:: 3.7 + + .. _asyncio-hello-world-coroutine: Example: Hello World coroutine @@ -104,10 +122,7 @@ Example of coroutine displaying ``"Hello World"``:: async def hello_world(): print("Hello World!") - loop = asyncio.get_event_loop() - # Blocking call which returns when the hello_world() coroutine is done - loop.run_until_complete(hello_world()) - loop.close() + asyncio.run(hello_world()) .. seealso:: @@ -127,7 +142,8 @@ using the :meth:`sleep` function:: import asyncio import datetime - async def display_date(loop): + async def display_date(): + loop = asyncio.get_running_loop() end_time = loop.time() + 5.0 while True: print(datetime.datetime.now()) @@ -135,10 +151,7 @@ using the :meth:`sleep` function:: break await asyncio.sleep(1) - loop = asyncio.get_event_loop() - # Blocking call which returns when the display_date() coroutine is done - loop.run_until_complete(display_date(loop)) - loop.close() + asyncio.run(display_date()) .. seealso:: diff --git a/Lib/asyncio/__init__.py b/Lib/asyncio/__init__.py index dd6686de840..23ea055912e 100644 --- a/Lib/asyncio/__init__.py +++ b/Lib/asyncio/__init__.py @@ -11,6 +11,7 @@ from .futures import * from .locks import * from .protocols import * +from .runners import * from .queues import * from .streams import * from .subprocess import * @@ -23,6 +24,7 @@ futures.__all__ + locks.__all__ + protocols.__all__ + + runners.__all__ + queues.__all__ + streams.__all__ + subprocess.__all__ + diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py new file mode 100644 index 00000000000..94d94097ab9 --- /dev/null +++ b/Lib/asyncio/runners.py @@ -0,0 +1,48 @@ +__all__ = 'run', + +from . import coroutines +from . import events + + +def run(main, *, debug=False): + """Run a coroutine. + + This function runs the passed coroutine, taking care of + managing the asyncio event loop and finalizing asynchronous + generators. + + This function cannot be called when another asyncio event loop is + running in the same thread. + + If debug is True, the event loop will be run in debug mode. + + This function always creates a new event loop and closes it at the end. + It should be used as a main entry point for asyncio programs, and should + ideally only be called once. + + Example: + + async def main(): + await asyncio.sleep(1) + print('hello') + + asyncio.run(main()) + """ + if events._get_running_loop() is not None: + raise RuntimeError( + "asyncio.run() cannot be called from a running event loop") + + if not coroutines.iscoroutine(main): + raise ValueError("a coroutine was expected, got {!r}".format(main)) + + loop = events.new_event_loop() + try: + events.set_event_loop(loop) + loop.set_debug(debug) + return loop.run_until_complete(main) + finally: + try: + loop.run_until_complete(loop.shutdown_asyncgens()) + finally: + events.set_event_loop(None) + loop.close() diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py new file mode 100644 index 00000000000..c52bd9443ea --- /dev/null +++ b/Lib/test/test_asyncio/test_runners.py @@ -0,0 +1,100 @@ +import asyncio +import unittest + +from unittest import mock + + +class TestPolicy(asyncio.AbstractEventLoopPolicy): + + def __init__(self, loop_factory): + self.loop_factory = loop_factory + self.loop = None + + def get_event_loop(self): + # shouldn't ever be called by asyncio.run() + raise RuntimeError + + def new_event_loop(self): + return self.loop_factory() + + def set_event_loop(self, loop): + if loop is not None: + # we want to check if the loop is closed + # in BaseTest.tearDown + self.loop = loop + + +class BaseTest(unittest.TestCase): + + def new_loop(self): + loop = asyncio.BaseEventLoop() + loop._process_events = mock.Mock() + loop._selector = mock.Mock() + loop._selector.select.return_value = () + loop.shutdown_ag_run = False + + async def shutdown_asyncgens(): + loop.shutdown_ag_run = True + loop.shutdown_asyncgens = shutdown_asyncgens + + return loop + + def setUp(self): + super().setUp() + + policy = TestPolicy(self.new_loop) + asyncio.set_event_loop_policy(policy) + + def tearDown(self): + policy = asyncio.get_event_loop_policy() + if policy.loop is not None: + self.assertTrue(policy.loop.is_closed()) + self.assertTrue(policy.loop.shutdown_ag_run) + + asyncio.set_event_loop_policy(None) + super().tearDown() + + +class RunTests(BaseTest): + + def test_asyncio_run_return(self): + async def main(): + await asyncio.sleep(0) + return 42 + + self.assertEqual(asyncio.run(main()), 42) + + def test_asyncio_run_raises(self): + async def main(): + await asyncio.sleep(0) + raise ValueError('spam') + + with self.assertRaisesRegex(ValueError, 'spam'): + asyncio.run(main()) + + def test_asyncio_run_only_coro(self): + for o in {1, lambda: None}: + with self.subTest(obj=o), \ + self.assertRaisesRegex(ValueError, + 'a coroutine was expected'): + asyncio.run(o) + + def test_asyncio_run_debug(self): + async def main(expected): + loop = asyncio.get_event_loop() + self.assertIs(loop.get_debug(), expected) + + asyncio.run(main(False)) + asyncio.run(main(True), debug=True) + + def test_asyncio_run_from_running_loop(self): + async def main(): + coro = main() + try: + asyncio.run(coro) + finally: + coro.close() # Suppress ResourceWarning + + with self.assertRaisesRegex(RuntimeError, + 'cannot be called from a running'): + asyncio.run(main()) diff --git a/Misc/NEWS.d/next/Library/2017-12-13-16-47-38.bpo-32314.W4_U2j.rst b/Misc/NEWS.d/next/Library/2017-12-13-16-47-38.bpo-32314.W4_U2j.rst new file mode 100644 index 00000000000..416906c9662 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-13-16-47-38.bpo-32314.W4_U2j.rst @@ -0,0 +1 @@ +Implement asyncio.run(). From webhook-mailer at python.org Thu Dec 14 11:57:58 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 14 Dec 2017 16:57:58 -0000 Subject: [Python-checkins] bpo-32277: Fix exception raised from chmod(..., follow_symlinks=False) (#4797) Message-ID: https://github.com/python/cpython/commit/233ef249cc5c18d796fb581747179c5e062b4083 commit: 233ef249cc5c18d796fb581747179c5e062b4083 branch: master author: Anthony Sottile committer: Serhiy Storchaka date: 2017-12-14T18:57:55+02:00 summary: bpo-32277: Fix exception raised from chmod(..., follow_symlinks=False) (#4797) files: A Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst M Modules/posixmodule.c diff --git a/Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst b/Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst new file mode 100644 index 00000000000..765527a6553 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst @@ -0,0 +1,3 @@ +Raise ``NotImplementedError`` instead of ``SystemError`` on platforms where +``chmod(..., follow_symlinks=False)`` is not supported. Patch by Anthony +Sottile. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index de32327b304..fb879e3821a 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2827,6 +2827,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, dir_fd, follow_symlinks); else follow_symlinks_specified("chmod", follow_symlinks); + return NULL; } else #endif From webhook-mailer at python.org Thu Dec 14 12:30:53 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 14 Dec 2017 17:30:53 -0000 Subject: [Python-checkins] bpo-32277: Fix exception raised from chmod(..., follow_symlinks=False) (GH-4797) (#4869) Message-ID: https://github.com/python/cpython/commit/d1cb1067a82b11280204e36b695e786a5a3ca221 commit: d1cb1067a82b11280204e36b695e786a5a3ca221 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-14T19:30:45+02:00 summary: bpo-32277: Fix exception raised from chmod(..., follow_symlinks=False) (GH-4797) (#4869) (cherry picked from commit 233ef249cc5c18d796fb581747179c5e062b4083) files: A Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst M Modules/posixmodule.c diff --git a/Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst b/Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst new file mode 100644 index 00000000000..765527a6553 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-11-09-53-14.bpo-32277.jkKiVC.rst @@ -0,0 +1,3 @@ +Raise ``NotImplementedError`` instead of ``SystemError`` on platforms where +``chmod(..., follow_symlinks=False)`` is not supported. Patch by Anthony +Sottile. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ee27fa4dec6..821b64ccbca 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2790,6 +2790,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, dir_fd, follow_symlinks); else follow_symlinks_specified("chmod", follow_symlinks); + return NULL; } else #endif From webhook-mailer at python.org Thu Dec 14 13:24:34 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 14 Dec 2017 18:24:34 -0000 Subject: [Python-checkins] bpo-29469: Optimize literal lists and sets iterating on the AST level. (#4866) Message-ID: https://github.com/python/cpython/commit/15a8728415e765f57e37f431f09e5c5821a04063 commit: 15a8728415e765f57e37f431f09e5c5821a04063 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-14T20:24:31+02:00 summary: bpo-29469: Optimize literal lists and sets iterating on the AST level. (#4866) files: M Python/ast_opt.c M Python/importlib.h M Python/importlib_external.h M Python/peephole.c diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 80531cc6ac5..e92d6471f91 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -205,7 +205,7 @@ fold_binop(expr_ty node, PyArena *arena) } static PyObject* -make_const_tuple(asdl_seq *elts, int make_set) +make_const_tuple(asdl_seq *elts) { for (int i = 0; i < asdl_seq_LEN(elts); i++) { expr_ty e = (expr_ty)asdl_seq_GET(elts, i); @@ -225,11 +225,6 @@ make_const_tuple(asdl_seq *elts, int make_set) Py_INCREF(v); PyTuple_SET_ITEM(newval, i, v); } - - /* Need to create frozen_set instead. */ - if (make_set) { - Py_SETREF(newval, PyFrozenSet_New(newval)); - } return newval; } @@ -241,7 +236,7 @@ fold_tuple(expr_ty node, PyArena *arena) if (node->v.Tuple.ctx != Load) return 1; - newval = make_const_tuple(node->v.Tuple.elts, 0); + newval = make_const_tuple(node->v.Tuple.elts); return make_const(node, newval, arena); } @@ -268,38 +263,48 @@ fold_subscr(expr_ty node, PyArena *arena) return make_const(node, newval, arena); } +/* Change literal list or set of constants into constant + tuple or frozenset respectively. + Used for right operand of "in" and "not in" tests and for iterable + in "for" loop and comprehensions. +*/ +static int +fold_iter(expr_ty arg, PyArena *arena) +{ + PyObject *newval; + if (arg->kind == List_kind) { + newval = make_const_tuple(arg->v.List.elts); + } + else if (arg->kind == Set_kind) { + newval = make_const_tuple(arg->v.Set.elts); + if (newval) { + Py_SETREF(newval, PyFrozenSet_New(newval)); + } + } + else { + return 1; + } + return make_const(arg, newval, arena); +} + static int fold_compare(expr_ty node, PyArena *arena) { asdl_int_seq *ops; asdl_seq *args; - PyObject *newval; int i; ops = node->v.Compare.ops; args = node->v.Compare.comparators; /* TODO: optimize cases with literal arguments. */ - for (i = 0; i < asdl_seq_LEN(ops); i++) { - int op; - expr_ty arg; - asdl_seq *elts; - - op = asdl_seq_GET(ops, i); - arg = (expr_ty)asdl_seq_GET(args, i); - /* Change literal list or set in 'in' or 'not in' into - tuple or frozenset respectively. */ - /* TODO: do the same when list or set is used as iterable - in for loop and comprehensions? */ - if (op != In && op != NotIn) - continue; - if (arg->kind == List_kind) - elts = arg->v.List.elts; - else if (arg->kind == Set_kind) - elts = arg->v.Set.elts; - else continue; - - newval = make_const_tuple(elts, arg->kind == Set_kind); - make_const(arg, newval, arena); + /* Change literal list or set in 'in' or 'not in' into + tuple or frozenset respectively. */ + i = asdl_seq_LEN(ops) - 1; + int op = asdl_seq_GET(ops, i); + if (op == In || op == NotIn) { + if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena)) { + return 0; + } } return 1; } @@ -497,6 +502,8 @@ astfold_comprehension(comprehension_ty node_, PyArena* ctx_) CALL(astfold_expr, expr_ty, node_->target); CALL(astfold_expr, expr_ty, node_->iter); CALL_SEQ(astfold_expr, expr_ty, node_->ifs); + + CALL(fold_iter, expr_ty, node_->iter); return 1; } @@ -565,6 +572,8 @@ astfold_stmt(stmt_ty node_, PyArena* ctx_) CALL(astfold_expr, expr_ty, node_->v.For.iter); CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body); CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse); + + CALL(fold_iter, expr_ty, node_->v.For.iter); break; case AsyncFor_kind: CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target); diff --git a/Python/importlib.h b/Python/importlib.h index 7908ea8b6ab..a12c8424f63 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -54,1770 +54,1769 @@ const unsigned char _Py_M__importlib[] = { 111,110,32,111,102,32,116,104,105,115,32,109,111,100,117,108, 101,46,10,10,78,99,2,0,0,0,0,0,0,0,3,0, 0,0,7,0,0,0,67,0,0,0,115,60,0,0,0,120, - 40,100,6,68,0,93,32,125,2,116,0,124,1,124,2,131, + 40,100,1,68,0,93,32,125,2,116,0,124,1,124,2,131, 2,114,6,116,1,124,0,124,2,116,2,124,1,124,2,131, 2,131,3,1,0,113,6,87,0,124,0,106,3,160,4,124, - 1,106,3,161,1,1,0,100,5,83,0,41,7,122,47,83, + 1,106,3,161,1,1,0,100,2,83,0,41,3,122,47,83, 105,109,112,108,101,32,115,117,98,115,116,105,116,117,116,101, 32,102,111,114,32,102,117,110,99,116,111,111,108,115,46,117, - 112,100,97,116,101,95,119,114,97,112,112,101,114,46,218,10, - 95,95,109,111,100,117,108,101,95,95,218,8,95,95,110,97, - 109,101,95,95,218,12,95,95,113,117,97,108,110,97,109,101, - 95,95,218,7,95,95,100,111,99,95,95,78,41,4,114,0, - 0,0,0,114,1,0,0,0,114,2,0,0,0,114,3,0, - 0,0,41,5,218,7,104,97,115,97,116,116,114,218,7,115, - 101,116,97,116,116,114,218,7,103,101,116,97,116,116,114,218, - 8,95,95,100,105,99,116,95,95,218,6,117,112,100,97,116, - 101,41,3,90,3,110,101,119,90,3,111,108,100,218,7,114, - 101,112,108,97,99,101,169,0,114,10,0,0,0,250,29,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,62,218,5,95,119, - 114,97,112,27,0,0,0,115,8,0,0,0,0,2,10,1, - 10,1,22,1,114,12,0,0,0,99,1,0,0,0,0,0, - 0,0,1,0,0,0,2,0,0,0,67,0,0,0,115,12, - 0,0,0,116,0,116,1,131,1,124,0,131,1,83,0,41, - 1,78,41,2,218,4,116,121,112,101,218,3,115,121,115,41, - 1,218,4,110,97,109,101,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,11,95,110,101,119,95,109,111,100, - 117,108,101,35,0,0,0,115,2,0,0,0,0,1,114,16, - 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 1,0,0,0,64,0,0,0,115,12,0,0,0,101,0,90, - 1,100,0,90,2,100,1,83,0,41,2,218,14,95,68,101, - 97,100,108,111,99,107,69,114,114,111,114,78,41,3,114,1, - 0,0,0,114,0,0,0,0,114,2,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,17,0,0,0,48,0,0,0,115,2,0,0,0,8, - 1,114,17,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,64,0,0,0,115,56,0,0,0, - 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, - 132,0,90,4,100,4,100,5,132,0,90,5,100,6,100,7, - 132,0,90,6,100,8,100,9,132,0,90,7,100,10,100,11, - 132,0,90,8,100,12,83,0,41,13,218,11,95,77,111,100, - 117,108,101,76,111,99,107,122,169,65,32,114,101,99,117,114, - 115,105,118,101,32,108,111,99,107,32,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,32,119,104,105,99,104,32,105, - 115,32,97,98,108,101,32,116,111,32,100,101,116,101,99,116, - 32,100,101,97,100,108,111,99,107,115,10,32,32,32,32,40, - 101,46,103,46,32,116,104,114,101,97,100,32,49,32,116,114, - 121,105,110,103,32,116,111,32,116,97,107,101,32,108,111,99, - 107,115,32,65,32,116,104,101,110,32,66,44,32,97,110,100, - 32,116,104,114,101,97,100,32,50,32,116,114,121,105,110,103, - 32,116,111,10,32,32,32,32,116,97,107,101,32,108,111,99, - 107,115,32,66,32,116,104,101,110,32,65,41,46,10,32,32, - 32,32,99,2,0,0,0,0,0,0,0,2,0,0,0,2, - 0,0,0,67,0,0,0,115,48,0,0,0,116,0,160,1, - 161,0,124,0,95,2,116,0,160,1,161,0,124,0,95,3, - 124,1,124,0,95,4,100,0,124,0,95,5,100,1,124,0, - 95,6,100,1,124,0,95,7,100,0,83,0,41,2,78,233, - 0,0,0,0,41,8,218,7,95,116,104,114,101,97,100,90, - 13,97,108,108,111,99,97,116,101,95,108,111,99,107,218,4, - 108,111,99,107,218,6,119,97,107,101,117,112,114,15,0,0, - 0,218,5,111,119,110,101,114,218,5,99,111,117,110,116,218, - 7,119,97,105,116,101,114,115,41,2,218,4,115,101,108,102, - 114,15,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,8,95,95,105,110,105,116,95,95,58,0, - 0,0,115,12,0,0,0,0,1,10,1,10,1,6,1,6, - 1,6,1,122,20,95,77,111,100,117,108,101,76,111,99,107, - 46,95,95,105,110,105,116,95,95,99,1,0,0,0,0,0, - 0,0,4,0,0,0,3,0,0,0,67,0,0,0,115,64, - 0,0,0,116,0,160,1,161,0,125,1,124,0,106,2,125, - 2,120,44,116,3,160,4,124,2,161,1,125,3,124,3,100, - 0,107,8,114,38,100,1,83,0,124,3,106,2,125,2,124, - 2,124,1,107,2,114,16,100,2,83,0,113,16,87,0,100, - 0,83,0,41,3,78,70,84,41,5,114,20,0,0,0,218, - 9,103,101,116,95,105,100,101,110,116,114,23,0,0,0,218, - 12,95,98,108,111,99,107,105,110,103,95,111,110,218,3,103, - 101,116,41,4,114,26,0,0,0,90,2,109,101,218,3,116, - 105,100,114,21,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,12,104,97,115,95,100,101,97,100, - 108,111,99,107,66,0,0,0,115,18,0,0,0,0,2,8, - 1,6,1,2,1,10,1,8,1,4,1,6,1,8,1,122, - 24,95,77,111,100,117,108,101,76,111,99,107,46,104,97,115, - 95,100,101,97,100,108,111,99,107,99,1,0,0,0,0,0, - 0,0,2,0,0,0,16,0,0,0,67,0,0,0,115,168, - 0,0,0,116,0,160,1,161,0,125,1,124,0,116,2,124, - 1,60,0,122,138,120,132,124,0,106,3,143,96,1,0,124, - 0,106,4,100,1,107,2,115,48,124,0,106,5,124,1,107, - 2,114,72,124,1,124,0,95,5,124,0,4,0,106,4,100, - 2,55,0,2,0,95,4,100,3,83,0,124,0,160,6,161, - 0,114,92,116,7,100,4,124,0,22,0,131,1,130,1,124, - 0,106,8,160,9,100,5,161,1,114,118,124,0,4,0,106, - 10,100,2,55,0,2,0,95,10,87,0,100,6,81,0,82, - 0,88,0,124,0,106,8,160,9,161,0,1,0,124,0,106, - 8,160,11,161,0,1,0,113,20,87,0,87,0,100,6,116, - 2,124,1,61,0,88,0,100,6,83,0,41,7,122,185,10, - 32,32,32,32,32,32,32,32,65,99,113,117,105,114,101,32, - 116,104,101,32,109,111,100,117,108,101,32,108,111,99,107,46, - 32,32,73,102,32,97,32,112,111,116,101,110,116,105,97,108, - 32,100,101,97,100,108,111,99,107,32,105,115,32,100,101,116, - 101,99,116,101,100,44,10,32,32,32,32,32,32,32,32,97, - 32,95,68,101,97,100,108,111,99,107,69,114,114,111,114,32, - 105,115,32,114,97,105,115,101,100,46,10,32,32,32,32,32, - 32,32,32,79,116,104,101,114,119,105,115,101,44,32,116,104, - 101,32,108,111,99,107,32,105,115,32,97,108,119,97,121,115, - 32,97,99,113,117,105,114,101,100,32,97,110,100,32,84,114, - 117,101,32,105,115,32,114,101,116,117,114,110,101,100,46,10, - 32,32,32,32,32,32,32,32,114,19,0,0,0,233,1,0, - 0,0,84,122,23,100,101,97,100,108,111,99,107,32,100,101, - 116,101,99,116,101,100,32,98,121,32,37,114,70,78,41,12, - 114,20,0,0,0,114,28,0,0,0,114,29,0,0,0,114, - 21,0,0,0,114,24,0,0,0,114,23,0,0,0,114,32, - 0,0,0,114,17,0,0,0,114,22,0,0,0,218,7,97, - 99,113,117,105,114,101,114,25,0,0,0,218,7,114,101,108, - 101,97,115,101,41,2,114,26,0,0,0,114,31,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 34,0,0,0,78,0,0,0,115,32,0,0,0,0,6,8, - 1,8,1,2,1,2,1,8,1,20,1,6,1,14,1,4, - 1,8,1,12,1,12,1,24,2,10,1,18,2,122,19,95, - 77,111,100,117,108,101,76,111,99,107,46,97,99,113,117,105, - 114,101,99,1,0,0,0,0,0,0,0,2,0,0,0,10, - 0,0,0,67,0,0,0,115,122,0,0,0,116,0,160,1, - 161,0,125,1,124,0,106,2,143,98,1,0,124,0,106,3, - 124,1,107,3,114,34,116,4,100,1,131,1,130,1,124,0, - 106,5,100,2,107,4,115,48,116,6,130,1,124,0,4,0, - 106,5,100,3,56,0,2,0,95,5,124,0,106,5,100,2, - 107,2,114,108,100,0,124,0,95,3,124,0,106,7,114,108, - 124,0,4,0,106,7,100,3,56,0,2,0,95,7,124,0, - 106,8,160,9,161,0,1,0,87,0,100,0,81,0,82,0, - 88,0,100,0,83,0,41,4,78,122,31,99,97,110,110,111, - 116,32,114,101,108,101,97,115,101,32,117,110,45,97,99,113, - 117,105,114,101,100,32,108,111,99,107,114,19,0,0,0,114, - 33,0,0,0,41,10,114,20,0,0,0,114,28,0,0,0, - 114,21,0,0,0,114,23,0,0,0,218,12,82,117,110,116, - 105,109,101,69,114,114,111,114,114,24,0,0,0,218,14,65, - 115,115,101,114,116,105,111,110,69,114,114,111,114,114,25,0, - 0,0,114,22,0,0,0,114,35,0,0,0,41,2,114,26, - 0,0,0,114,31,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,35,0,0,0,103,0,0,0, - 115,22,0,0,0,0,1,8,1,8,1,10,1,8,1,14, - 1,14,1,10,1,6,1,6,1,14,1,122,19,95,77,111, - 100,117,108,101,76,111,99,107,46,114,101,108,101,97,115,101, - 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, - 0,67,0,0,0,115,18,0,0,0,100,1,160,0,124,0, - 106,1,116,2,124,0,131,1,161,2,83,0,41,2,78,122, - 23,95,77,111,100,117,108,101,76,111,99,107,40,123,33,114, - 125,41,32,97,116,32,123,125,41,3,218,6,102,111,114,109, - 97,116,114,15,0,0,0,218,2,105,100,41,1,114,26,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,8,95,95,114,101,112,114,95,95,116,0,0,0,115, - 2,0,0,0,0,1,122,20,95,77,111,100,117,108,101,76, - 111,99,107,46,95,95,114,101,112,114,95,95,78,41,9,114, - 1,0,0,0,114,0,0,0,0,114,2,0,0,0,114,3, - 0,0,0,114,27,0,0,0,114,32,0,0,0,114,34,0, - 0,0,114,35,0,0,0,114,40,0,0,0,114,10,0,0, + 112,100,97,116,101,95,119,114,97,112,112,101,114,46,41,4, + 218,10,95,95,109,111,100,117,108,101,95,95,218,8,95,95, + 110,97,109,101,95,95,218,12,95,95,113,117,97,108,110,97, + 109,101,95,95,218,7,95,95,100,111,99,95,95,78,41,5, + 218,7,104,97,115,97,116,116,114,218,7,115,101,116,97,116, + 116,114,218,7,103,101,116,97,116,116,114,218,8,95,95,100, + 105,99,116,95,95,218,6,117,112,100,97,116,101,41,3,90, + 3,110,101,119,90,3,111,108,100,218,7,114,101,112,108,97, + 99,101,169,0,114,10,0,0,0,250,29,60,102,114,111,122, + 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, + 111,116,115,116,114,97,112,62,218,5,95,119,114,97,112,27, + 0,0,0,115,8,0,0,0,0,2,10,1,10,1,22,1, + 114,12,0,0,0,99,1,0,0,0,0,0,0,0,1,0, + 0,0,2,0,0,0,67,0,0,0,115,12,0,0,0,116, + 0,116,1,131,1,124,0,131,1,83,0,41,1,78,41,2, + 218,4,116,121,112,101,218,3,115,121,115,41,1,218,4,110, + 97,109,101,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,218,11,95,110,101,119,95,109,111,100,117,108,101,35, + 0,0,0,115,2,0,0,0,0,1,114,16,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 64,0,0,0,115,12,0,0,0,101,0,90,1,100,0,90, + 2,100,1,83,0,41,2,218,14,95,68,101,97,100,108,111, + 99,107,69,114,114,111,114,78,41,3,114,1,0,0,0,114, + 0,0,0,0,114,2,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,17,0, + 0,0,48,0,0,0,115,2,0,0,0,8,1,114,17,0, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,64,0,0,0,115,56,0,0,0,101,0,90,1, + 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, + 100,4,100,5,132,0,90,5,100,6,100,7,132,0,90,6, + 100,8,100,9,132,0,90,7,100,10,100,11,132,0,90,8, + 100,12,83,0,41,13,218,11,95,77,111,100,117,108,101,76, + 111,99,107,122,169,65,32,114,101,99,117,114,115,105,118,101, + 32,108,111,99,107,32,105,109,112,108,101,109,101,110,116,97, + 116,105,111,110,32,119,104,105,99,104,32,105,115,32,97,98, + 108,101,32,116,111,32,100,101,116,101,99,116,32,100,101,97, + 100,108,111,99,107,115,10,32,32,32,32,40,101,46,103,46, + 32,116,104,114,101,97,100,32,49,32,116,114,121,105,110,103, + 32,116,111,32,116,97,107,101,32,108,111,99,107,115,32,65, + 32,116,104,101,110,32,66,44,32,97,110,100,32,116,104,114, + 101,97,100,32,50,32,116,114,121,105,110,103,32,116,111,10, + 32,32,32,32,116,97,107,101,32,108,111,99,107,115,32,66, + 32,116,104,101,110,32,65,41,46,10,32,32,32,32,99,2, + 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, + 0,0,0,115,48,0,0,0,116,0,160,1,161,0,124,0, + 95,2,116,0,160,1,161,0,124,0,95,3,124,1,124,0, + 95,4,100,0,124,0,95,5,100,1,124,0,95,6,100,1, + 124,0,95,7,100,0,83,0,41,2,78,233,0,0,0,0, + 41,8,218,7,95,116,104,114,101,97,100,90,13,97,108,108, + 111,99,97,116,101,95,108,111,99,107,218,4,108,111,99,107, + 218,6,119,97,107,101,117,112,114,15,0,0,0,218,5,111, + 119,110,101,114,218,5,99,111,117,110,116,218,7,119,97,105, + 116,101,114,115,41,2,218,4,115,101,108,102,114,15,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,18,0,0,0,52,0,0,0,115,10,0,0,0,12,6, - 8,8,8,12,8,25,8,13,114,18,0,0,0,99,0,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, - 0,0,115,48,0,0,0,101,0,90,1,100,0,90,2,100, - 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, - 0,90,5,100,6,100,7,132,0,90,6,100,8,100,9,132, - 0,90,7,100,10,83,0,41,11,218,16,95,68,117,109,109, - 121,77,111,100,117,108,101,76,111,99,107,122,86,65,32,115, - 105,109,112,108,101,32,95,77,111,100,117,108,101,76,111,99, - 107,32,101,113,117,105,118,97,108,101,110,116,32,102,111,114, - 32,80,121,116,104,111,110,32,98,117,105,108,100,115,32,119, - 105,116,104,111,117,116,10,32,32,32,32,109,117,108,116,105, - 45,116,104,114,101,97,100,105,110,103,32,115,117,112,112,111, - 114,116,46,99,2,0,0,0,0,0,0,0,2,0,0,0, - 2,0,0,0,67,0,0,0,115,16,0,0,0,124,1,124, - 0,95,0,100,1,124,0,95,1,100,0,83,0,41,2,78, - 114,19,0,0,0,41,2,114,15,0,0,0,114,24,0,0, - 0,41,2,114,26,0,0,0,114,15,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,27,0,0, - 0,124,0,0,0,115,4,0,0,0,0,1,6,1,122,25, - 95,68,117,109,109,121,77,111,100,117,108,101,76,111,99,107, - 46,95,95,105,110,105,116,95,95,99,1,0,0,0,0,0, - 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,18, - 0,0,0,124,0,4,0,106,0,100,1,55,0,2,0,95, - 0,100,2,83,0,41,3,78,114,33,0,0,0,84,41,1, - 114,24,0,0,0,41,1,114,26,0,0,0,114,10,0,0, + 218,8,95,95,105,110,105,116,95,95,58,0,0,0,115,12, + 0,0,0,0,1,10,1,10,1,6,1,6,1,6,1,122, + 20,95,77,111,100,117,108,101,76,111,99,107,46,95,95,105, + 110,105,116,95,95,99,1,0,0,0,0,0,0,0,4,0, + 0,0,3,0,0,0,67,0,0,0,115,64,0,0,0,116, + 0,160,1,161,0,125,1,124,0,106,2,125,2,120,44,116, + 3,160,4,124,2,161,1,125,3,124,3,100,0,107,8,114, + 38,100,1,83,0,124,3,106,2,125,2,124,2,124,1,107, + 2,114,16,100,2,83,0,113,16,87,0,100,0,83,0,41, + 3,78,70,84,41,5,114,20,0,0,0,218,9,103,101,116, + 95,105,100,101,110,116,114,23,0,0,0,218,12,95,98,108, + 111,99,107,105,110,103,95,111,110,218,3,103,101,116,41,4, + 114,26,0,0,0,90,2,109,101,218,3,116,105,100,114,21, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,218,12,104,97,115,95,100,101,97,100,108,111,99,107, + 66,0,0,0,115,18,0,0,0,0,2,8,1,6,1,2, + 1,10,1,8,1,4,1,6,1,8,1,122,24,95,77,111, + 100,117,108,101,76,111,99,107,46,104,97,115,95,100,101,97, + 100,108,111,99,107,99,1,0,0,0,0,0,0,0,2,0, + 0,0,16,0,0,0,67,0,0,0,115,168,0,0,0,116, + 0,160,1,161,0,125,1,124,0,116,2,124,1,60,0,122, + 138,120,132,124,0,106,3,143,96,1,0,124,0,106,4,100, + 1,107,2,115,48,124,0,106,5,124,1,107,2,114,72,124, + 1,124,0,95,5,124,0,4,0,106,4,100,2,55,0,2, + 0,95,4,100,3,83,0,124,0,160,6,161,0,114,92,116, + 7,100,4,124,0,22,0,131,1,130,1,124,0,106,8,160, + 9,100,5,161,1,114,118,124,0,4,0,106,10,100,2,55, + 0,2,0,95,10,87,0,100,6,81,0,82,0,88,0,124, + 0,106,8,160,9,161,0,1,0,124,0,106,8,160,11,161, + 0,1,0,113,20,87,0,87,0,100,6,116,2,124,1,61, + 0,88,0,100,6,83,0,41,7,122,185,10,32,32,32,32, + 32,32,32,32,65,99,113,117,105,114,101,32,116,104,101,32, + 109,111,100,117,108,101,32,108,111,99,107,46,32,32,73,102, + 32,97,32,112,111,116,101,110,116,105,97,108,32,100,101,97, + 100,108,111,99,107,32,105,115,32,100,101,116,101,99,116,101, + 100,44,10,32,32,32,32,32,32,32,32,97,32,95,68,101, + 97,100,108,111,99,107,69,114,114,111,114,32,105,115,32,114, + 97,105,115,101,100,46,10,32,32,32,32,32,32,32,32,79, + 116,104,101,114,119,105,115,101,44,32,116,104,101,32,108,111, + 99,107,32,105,115,32,97,108,119,97,121,115,32,97,99,113, + 117,105,114,101,100,32,97,110,100,32,84,114,117,101,32,105, + 115,32,114,101,116,117,114,110,101,100,46,10,32,32,32,32, + 32,32,32,32,114,19,0,0,0,233,1,0,0,0,84,122, + 23,100,101,97,100,108,111,99,107,32,100,101,116,101,99,116, + 101,100,32,98,121,32,37,114,70,78,41,12,114,20,0,0, + 0,114,28,0,0,0,114,29,0,0,0,114,21,0,0,0, + 114,24,0,0,0,114,23,0,0,0,114,32,0,0,0,114, + 17,0,0,0,114,22,0,0,0,218,7,97,99,113,117,105, + 114,101,114,25,0,0,0,218,7,114,101,108,101,97,115,101, + 41,2,114,26,0,0,0,114,31,0,0,0,114,10,0,0, 0,114,10,0,0,0,114,11,0,0,0,114,34,0,0,0, - 128,0,0,0,115,4,0,0,0,0,1,14,1,122,24,95, - 68,117,109,109,121,77,111,100,117,108,101,76,111,99,107,46, - 97,99,113,117,105,114,101,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,36,0,0, - 0,124,0,106,0,100,1,107,2,114,18,116,1,100,2,131, - 1,130,1,124,0,4,0,106,0,100,3,56,0,2,0,95, - 0,100,0,83,0,41,4,78,114,19,0,0,0,122,31,99, - 97,110,110,111,116,32,114,101,108,101,97,115,101,32,117,110, - 45,97,99,113,117,105,114,101,100,32,108,111,99,107,114,33, - 0,0,0,41,2,114,24,0,0,0,114,36,0,0,0,41, - 1,114,26,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,35,0,0,0,132,0,0,0,115,6, - 0,0,0,0,1,10,1,8,1,122,24,95,68,117,109,109, - 121,77,111,100,117,108,101,76,111,99,107,46,114,101,108,101, - 97,115,101,99,1,0,0,0,0,0,0,0,1,0,0,0, - 5,0,0,0,67,0,0,0,115,18,0,0,0,100,1,160, - 0,124,0,106,1,116,2,124,0,131,1,161,2,83,0,41, - 2,78,122,28,95,68,117,109,109,121,77,111,100,117,108,101, - 76,111,99,107,40,123,33,114,125,41,32,97,116,32,123,125, - 41,3,114,38,0,0,0,114,15,0,0,0,114,39,0,0, - 0,41,1,114,26,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,40,0,0,0,137,0,0,0, - 115,2,0,0,0,0,1,122,25,95,68,117,109,109,121,77, - 111,100,117,108,101,76,111,99,107,46,95,95,114,101,112,114, - 95,95,78,41,8,114,1,0,0,0,114,0,0,0,0,114, - 2,0,0,0,114,3,0,0,0,114,27,0,0,0,114,34, - 0,0,0,114,35,0,0,0,114,40,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,41,0,0,0,120,0,0,0,115,8,0,0,0,12, - 4,8,4,8,4,8,5,114,41,0,0,0,99,0,0,0, - 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, - 0,115,36,0,0,0,101,0,90,1,100,0,90,2,100,1, - 100,2,132,0,90,3,100,3,100,4,132,0,90,4,100,5, - 100,6,132,0,90,5,100,7,83,0,41,8,218,18,95,77, - 111,100,117,108,101,76,111,99,107,77,97,110,97,103,101,114, - 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, - 0,67,0,0,0,115,16,0,0,0,124,1,124,0,95,0, - 100,0,124,0,95,1,100,0,83,0,41,1,78,41,2,218, - 5,95,110,97,109,101,218,5,95,108,111,99,107,41,2,114, + 78,0,0,0,115,32,0,0,0,0,6,8,1,8,1,2, + 1,2,1,8,1,20,1,6,1,14,1,4,1,8,1,12, + 1,12,1,24,2,10,1,18,2,122,19,95,77,111,100,117, + 108,101,76,111,99,107,46,97,99,113,117,105,114,101,99,1, + 0,0,0,0,0,0,0,2,0,0,0,10,0,0,0,67, + 0,0,0,115,122,0,0,0,116,0,160,1,161,0,125,1, + 124,0,106,2,143,98,1,0,124,0,106,3,124,1,107,3, + 114,34,116,4,100,1,131,1,130,1,124,0,106,5,100,2, + 107,4,115,48,116,6,130,1,124,0,4,0,106,5,100,3, + 56,0,2,0,95,5,124,0,106,5,100,2,107,2,114,108, + 100,0,124,0,95,3,124,0,106,7,114,108,124,0,4,0, + 106,7,100,3,56,0,2,0,95,7,124,0,106,8,160,9, + 161,0,1,0,87,0,100,0,81,0,82,0,88,0,100,0, + 83,0,41,4,78,122,31,99,97,110,110,111,116,32,114,101, + 108,101,97,115,101,32,117,110,45,97,99,113,117,105,114,101, + 100,32,108,111,99,107,114,19,0,0,0,114,33,0,0,0, + 41,10,114,20,0,0,0,114,28,0,0,0,114,21,0,0, + 0,114,23,0,0,0,218,12,82,117,110,116,105,109,101,69, + 114,114,111,114,114,24,0,0,0,218,14,65,115,115,101,114, + 116,105,111,110,69,114,114,111,114,114,25,0,0,0,114,22, + 0,0,0,114,35,0,0,0,41,2,114,26,0,0,0,114, + 31,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,35,0,0,0,103,0,0,0,115,22,0,0, + 0,0,1,8,1,8,1,10,1,8,1,14,1,14,1,10, + 1,6,1,6,1,14,1,122,19,95,77,111,100,117,108,101, + 76,111,99,107,46,114,101,108,101,97,115,101,99,1,0,0, + 0,0,0,0,0,1,0,0,0,5,0,0,0,67,0,0, + 0,115,18,0,0,0,100,1,160,0,124,0,106,1,116,2, + 124,0,131,1,161,2,83,0,41,2,78,122,23,95,77,111, + 100,117,108,101,76,111,99,107,40,123,33,114,125,41,32,97, + 116,32,123,125,41,3,218,6,102,111,114,109,97,116,114,15, + 0,0,0,218,2,105,100,41,1,114,26,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,218,8,95, + 95,114,101,112,114,95,95,116,0,0,0,115,2,0,0,0, + 0,1,122,20,95,77,111,100,117,108,101,76,111,99,107,46, + 95,95,114,101,112,114,95,95,78,41,9,114,1,0,0,0, + 114,0,0,0,0,114,2,0,0,0,114,3,0,0,0,114, + 27,0,0,0,114,32,0,0,0,114,34,0,0,0,114,35, + 0,0,0,114,40,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,18,0,0, + 0,52,0,0,0,115,10,0,0,0,12,6,8,8,8,12, + 8,25,8,13,114,18,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,48, + 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, + 6,100,7,132,0,90,6,100,8,100,9,132,0,90,7,100, + 10,83,0,41,11,218,16,95,68,117,109,109,121,77,111,100, + 117,108,101,76,111,99,107,122,86,65,32,115,105,109,112,108, + 101,32,95,77,111,100,117,108,101,76,111,99,107,32,101,113, + 117,105,118,97,108,101,110,116,32,102,111,114,32,80,121,116, + 104,111,110,32,98,117,105,108,100,115,32,119,105,116,104,111, + 117,116,10,32,32,32,32,109,117,108,116,105,45,116,104,114, + 101,97,100,105,110,103,32,115,117,112,112,111,114,116,46,99, + 2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, + 67,0,0,0,115,16,0,0,0,124,1,124,0,95,0,100, + 1,124,0,95,1,100,0,83,0,41,2,78,114,19,0,0, + 0,41,2,114,15,0,0,0,114,24,0,0,0,41,2,114, 26,0,0,0,114,15,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,27,0,0,0,143,0,0, - 0,115,4,0,0,0,0,1,6,1,122,27,95,77,111,100, - 117,108,101,76,111,99,107,77,97,110,97,103,101,114,46,95, - 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,2,0,0,0,67,0,0,0,115,26,0,0, - 0,116,0,124,0,106,1,131,1,124,0,95,2,124,0,106, - 2,160,3,161,0,1,0,100,0,83,0,41,1,78,41,4, - 218,16,95,103,101,116,95,109,111,100,117,108,101,95,108,111, - 99,107,114,43,0,0,0,114,44,0,0,0,114,34,0,0, + 0,0,0,114,11,0,0,0,114,27,0,0,0,124,0,0, + 0,115,4,0,0,0,0,1,6,1,122,25,95,68,117,109, + 109,121,77,111,100,117,108,101,76,111,99,107,46,95,95,105, + 110,105,116,95,95,99,1,0,0,0,0,0,0,0,1,0, + 0,0,3,0,0,0,67,0,0,0,115,18,0,0,0,124, + 0,4,0,106,0,100,1,55,0,2,0,95,0,100,2,83, + 0,41,3,78,114,33,0,0,0,84,41,1,114,24,0,0, 0,41,1,114,26,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,9,95,95,101,110,116,101,114, - 95,95,147,0,0,0,115,4,0,0,0,0,1,12,1,122, - 28,95,77,111,100,117,108,101,76,111,99,107,77,97,110,97, - 103,101,114,46,95,95,101,110,116,101,114,95,95,99,1,0, - 0,0,0,0,0,0,3,0,0,0,2,0,0,0,79,0, - 0,0,115,14,0,0,0,124,0,106,0,160,1,161,0,1, - 0,100,0,83,0,41,1,78,41,2,114,44,0,0,0,114, - 35,0,0,0,41,3,114,26,0,0,0,218,4,97,114,103, - 115,90,6,107,119,97,114,103,115,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,8,95,95,101,120,105,116, - 95,95,151,0,0,0,115,2,0,0,0,0,1,122,27,95, - 77,111,100,117,108,101,76,111,99,107,77,97,110,97,103,101, - 114,46,95,95,101,120,105,116,95,95,78,41,6,114,1,0, - 0,0,114,0,0,0,0,114,2,0,0,0,114,27,0,0, - 0,114,46,0,0,0,114,48,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 42,0,0,0,141,0,0,0,115,6,0,0,0,8,2,8, - 4,8,4,114,42,0,0,0,99,1,0,0,0,0,0,0, - 0,3,0,0,0,18,0,0,0,67,0,0,0,115,130,0, - 0,0,116,0,160,1,161,0,1,0,122,106,121,14,116,2, - 124,0,25,0,131,0,125,1,87,0,110,24,4,0,116,3, - 107,10,114,48,1,0,1,0,1,0,100,1,125,1,89,0, - 110,2,88,0,124,1,100,1,107,8,114,112,116,4,100,1, - 107,8,114,76,116,5,124,0,131,1,125,1,110,8,116,6, - 124,0,131,1,125,1,124,0,102,1,100,2,100,3,132,1, - 125,2,116,7,160,8,124,1,124,2,161,2,116,2,124,0, - 60,0,87,0,100,1,116,0,160,9,161,0,1,0,88,0, - 124,1,83,0,41,4,122,139,71,101,116,32,111,114,32,99, - 114,101,97,116,101,32,116,104,101,32,109,111,100,117,108,101, - 32,108,111,99,107,32,102,111,114,32,97,32,103,105,118,101, - 110,32,109,111,100,117,108,101,32,110,97,109,101,46,10,10, - 32,32,32,32,65,99,113,117,105,114,101,47,114,101,108,101, - 97,115,101,32,105,110,116,101,114,110,97,108,108,121,32,116, - 104,101,32,103,108,111,98,97,108,32,105,109,112,111,114,116, - 32,108,111,99,107,32,116,111,32,112,114,111,116,101,99,116, - 10,32,32,32,32,95,109,111,100,117,108,101,95,108,111,99, - 107,115,46,78,99,2,0,0,0,0,0,0,0,2,0,0, - 0,11,0,0,0,83,0,0,0,115,48,0,0,0,116,0, - 160,1,161,0,1,0,122,24,116,2,160,3,124,1,161,1, - 124,0,107,8,114,30,116,2,124,1,61,0,87,0,100,0, - 116,0,160,4,161,0,1,0,88,0,100,0,83,0,41,1, - 78,41,5,218,4,95,105,109,112,218,12,97,99,113,117,105, - 114,101,95,108,111,99,107,218,13,95,109,111,100,117,108,101, - 95,108,111,99,107,115,114,30,0,0,0,218,12,114,101,108, - 101,97,115,101,95,108,111,99,107,41,2,218,3,114,101,102, + 0,0,114,11,0,0,0,114,34,0,0,0,128,0,0,0, + 115,4,0,0,0,0,1,14,1,122,24,95,68,117,109,109, + 121,77,111,100,117,108,101,76,111,99,107,46,97,99,113,117, + 105,114,101,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,36,0,0,0,124,0,106, + 0,100,1,107,2,114,18,116,1,100,2,131,1,130,1,124, + 0,4,0,106,0,100,3,56,0,2,0,95,0,100,0,83, + 0,41,4,78,114,19,0,0,0,122,31,99,97,110,110,111, + 116,32,114,101,108,101,97,115,101,32,117,110,45,97,99,113, + 117,105,114,101,100,32,108,111,99,107,114,33,0,0,0,41, + 2,114,24,0,0,0,114,36,0,0,0,41,1,114,26,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,35,0,0,0,132,0,0,0,115,6,0,0,0,0, + 1,10,1,8,1,122,24,95,68,117,109,109,121,77,111,100, + 117,108,101,76,111,99,107,46,114,101,108,101,97,115,101,99, + 1,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0, + 67,0,0,0,115,18,0,0,0,100,1,160,0,124,0,106, + 1,116,2,124,0,131,1,161,2,83,0,41,2,78,122,28, + 95,68,117,109,109,121,77,111,100,117,108,101,76,111,99,107, + 40,123,33,114,125,41,32,97,116,32,123,125,41,3,114,38, + 0,0,0,114,15,0,0,0,114,39,0,0,0,41,1,114, + 26,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,40,0,0,0,137,0,0,0,115,2,0,0, + 0,0,1,122,25,95,68,117,109,109,121,77,111,100,117,108, + 101,76,111,99,107,46,95,95,114,101,112,114,95,95,78,41, + 8,114,1,0,0,0,114,0,0,0,0,114,2,0,0,0, + 114,3,0,0,0,114,27,0,0,0,114,34,0,0,0,114, + 35,0,0,0,114,40,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,41,0, + 0,0,120,0,0,0,115,8,0,0,0,12,4,8,4,8, + 4,8,5,114,41,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,64,0,0,0,115,36,0, + 0,0,101,0,90,1,100,0,90,2,100,1,100,2,132,0, + 90,3,100,3,100,4,132,0,90,4,100,5,100,6,132,0, + 90,5,100,7,83,0,41,8,218,18,95,77,111,100,117,108, + 101,76,111,99,107,77,97,110,97,103,101,114,99,2,0,0, + 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, + 0,115,16,0,0,0,124,1,124,0,95,0,100,0,124,0, + 95,1,100,0,83,0,41,1,78,41,2,218,5,95,110,97, + 109,101,218,5,95,108,111,99,107,41,2,114,26,0,0,0, 114,15,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,2,99,98,176,0,0,0,115,10,0,0, - 0,0,1,8,1,2,4,14,1,10,2,122,28,95,103,101, - 116,95,109,111,100,117,108,101,95,108,111,99,107,46,60,108, - 111,99,97,108,115,62,46,99,98,41,10,114,49,0,0,0, - 114,50,0,0,0,114,51,0,0,0,218,8,75,101,121,69, - 114,114,111,114,114,20,0,0,0,114,41,0,0,0,114,18, - 0,0,0,218,8,95,119,101,97,107,114,101,102,114,53,0, - 0,0,114,52,0,0,0,41,3,114,15,0,0,0,114,21, - 0,0,0,114,54,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,45,0,0,0,157,0,0,0, - 115,28,0,0,0,0,6,8,1,2,1,2,1,14,1,14, - 1,10,2,8,1,8,1,10,2,8,2,12,11,20,2,10, - 2,114,45,0,0,0,99,1,0,0,0,0,0,0,0,2, - 0,0,0,11,0,0,0,67,0,0,0,115,54,0,0,0, - 116,0,124,0,131,1,125,1,121,12,124,1,160,1,161,0, - 1,0,87,0,110,20,4,0,116,2,107,10,114,40,1,0, - 1,0,1,0,89,0,110,10,88,0,124,1,160,3,161,0, - 1,0,100,1,83,0,41,2,122,189,65,99,113,117,105,114, - 101,115,32,116,104,101,110,32,114,101,108,101,97,115,101,115, - 32,116,104,101,32,109,111,100,117,108,101,32,108,111,99,107, - 32,102,111,114,32,97,32,103,105,118,101,110,32,109,111,100, - 117,108,101,32,110,97,109,101,46,10,10,32,32,32,32,84, - 104,105,115,32,105,115,32,117,115,101,100,32,116,111,32,101, - 110,115,117,114,101,32,97,32,109,111,100,117,108,101,32,105, - 115,32,99,111,109,112,108,101,116,101,108,121,32,105,110,105, - 116,105,97,108,105,122,101,100,44,32,105,110,32,116,104,101, - 10,32,32,32,32,101,118,101,110,116,32,105,116,32,105,115, - 32,98,101,105,110,103,32,105,109,112,111,114,116,101,100,32, - 98,121,32,97,110,111,116,104,101,114,32,116,104,114,101,97, - 100,46,10,32,32,32,32,78,41,4,114,45,0,0,0,114, - 34,0,0,0,114,17,0,0,0,114,35,0,0,0,41,2, - 114,15,0,0,0,114,21,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,19,95,108,111,99,107, - 95,117,110,108,111,99,107,95,109,111,100,117,108,101,194,0, - 0,0,115,12,0,0,0,0,6,8,1,2,1,12,1,14, - 3,6,2,114,57,0,0,0,99,1,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,79,0,0,0,115,10,0, - 0,0,124,0,124,1,124,2,142,1,83,0,41,1,97,46, - 1,0,0,114,101,109,111,118,101,95,105,109,112,111,114,116, - 108,105,98,95,102,114,97,109,101,115,32,105,110,32,105,109, - 112,111,114,116,46,99,32,119,105,108,108,32,97,108,119,97, - 121,115,32,114,101,109,111,118,101,32,115,101,113,117,101,110, - 99,101,115,10,32,32,32,32,111,102,32,105,109,112,111,114, - 116,108,105,98,32,102,114,97,109,101,115,32,116,104,97,116, - 32,101,110,100,32,119,105,116,104,32,97,32,99,97,108,108, - 32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111, - 110,10,10,32,32,32,32,85,115,101,32,105,116,32,105,110, - 115,116,101,97,100,32,111,102,32,97,32,110,111,114,109,97, - 108,32,99,97,108,108,32,105,110,32,112,108,97,99,101,115, - 32,119,104,101,114,101,32,105,110,99,108,117,100,105,110,103, - 32,116,104,101,32,105,109,112,111,114,116,108,105,98,10,32, - 32,32,32,102,114,97,109,101,115,32,105,110,116,114,111,100, - 117,99,101,115,32,117,110,119,97,110,116,101,100,32,110,111, - 105,115,101,32,105,110,116,111,32,116,104,101,32,116,114,97, - 99,101,98,97,99,107,32,40,101,46,103,46,32,119,104,101, - 110,32,101,120,101,99,117,116,105,110,103,10,32,32,32,32, - 109,111,100,117,108,101,32,99,111,100,101,41,10,32,32,32, - 32,114,10,0,0,0,41,3,218,1,102,114,47,0,0,0, - 90,4,107,119,100,115,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,218,25,95,99,97,108,108,95,119,105,116, - 104,95,102,114,97,109,101,115,95,114,101,109,111,118,101,100, - 211,0,0,0,115,2,0,0,0,0,8,114,59,0,0,0, - 114,33,0,0,0,41,1,218,9,118,101,114,98,111,115,105, - 116,121,99,1,0,0,0,1,0,0,0,3,0,0,0,4, - 0,0,0,71,0,0,0,115,54,0,0,0,116,0,106,1, - 106,2,124,1,107,5,114,50,124,0,160,3,100,1,161,1, - 115,30,100,2,124,0,23,0,125,0,116,4,124,0,106,5, - 124,2,142,0,116,0,106,6,100,3,141,2,1,0,100,4, - 83,0,41,5,122,61,80,114,105,110,116,32,116,104,101,32, - 109,101,115,115,97,103,101,32,116,111,32,115,116,100,101,114, - 114,32,105,102,32,45,118,47,80,89,84,72,79,78,86,69, - 82,66,79,83,69,32,105,115,32,116,117,114,110,101,100,32, - 111,110,46,41,2,250,1,35,122,7,105,109,112,111,114,116, - 32,122,2,35,32,41,1,90,4,102,105,108,101,78,41,7, - 114,14,0,0,0,218,5,102,108,97,103,115,218,7,118,101, - 114,98,111,115,101,218,10,115,116,97,114,116,115,119,105,116, - 104,218,5,112,114,105,110,116,114,38,0,0,0,218,6,115, - 116,100,101,114,114,41,3,218,7,109,101,115,115,97,103,101, - 114,60,0,0,0,114,47,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,16,95,118,101,114,98, - 111,115,101,95,109,101,115,115,97,103,101,222,0,0,0,115, - 8,0,0,0,0,2,12,1,10,1,8,1,114,68,0,0, - 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,3,0,0,0,115,26,0,0,0,135,0,102,1,100, - 1,100,2,132,8,125,1,116,0,124,1,136,0,131,2,1, - 0,124,1,83,0,41,3,122,49,68,101,99,111,114,97,116, - 111,114,32,116,111,32,118,101,114,105,102,121,32,116,104,101, - 32,110,97,109,101,100,32,109,111,100,117,108,101,32,105,115, - 32,98,117,105,108,116,45,105,110,46,99,2,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, - 38,0,0,0,124,1,116,0,106,1,107,7,114,28,116,2, - 100,1,160,3,124,1,161,1,124,1,100,2,141,2,130,1, - 136,0,124,0,124,1,131,2,83,0,41,3,78,122,29,123, - 33,114,125,32,105,115,32,110,111,116,32,97,32,98,117,105, - 108,116,45,105,110,32,109,111,100,117,108,101,41,1,114,15, - 0,0,0,41,4,114,14,0,0,0,218,20,98,117,105,108, - 116,105,110,95,109,111,100,117,108,101,95,110,97,109,101,115, - 218,11,73,109,112,111,114,116,69,114,114,111,114,114,38,0, - 0,0,41,2,114,26,0,0,0,218,8,102,117,108,108,110, - 97,109,101,41,1,218,3,102,120,110,114,10,0,0,0,114, - 11,0,0,0,218,25,95,114,101,113,117,105,114,101,115,95, - 98,117,105,108,116,105,110,95,119,114,97,112,112,101,114,232, - 0,0,0,115,8,0,0,0,0,1,10,1,10,1,8,1, - 122,52,95,114,101,113,117,105,114,101,115,95,98,117,105,108, - 116,105,110,46,60,108,111,99,97,108,115,62,46,95,114,101, - 113,117,105,114,101,115,95,98,117,105,108,116,105,110,95,119, - 114,97,112,112,101,114,41,1,114,12,0,0,0,41,2,114, - 72,0,0,0,114,73,0,0,0,114,10,0,0,0,41,1, - 114,72,0,0,0,114,11,0,0,0,218,17,95,114,101,113, - 117,105,114,101,115,95,98,117,105,108,116,105,110,230,0,0, - 0,115,6,0,0,0,0,2,12,5,10,1,114,74,0,0, - 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,3,0,0,0,115,26,0,0,0,135,0,102,1,100, - 1,100,2,132,8,125,1,116,0,124,1,136,0,131,2,1, - 0,124,1,83,0,41,3,122,47,68,101,99,111,114,97,116, - 111,114,32,116,111,32,118,101,114,105,102,121,32,116,104,101, - 32,110,97,109,101,100,32,109,111,100,117,108,101,32,105,115, - 32,102,114,111,122,101,110,46,99,2,0,0,0,0,0,0, - 0,2,0,0,0,4,0,0,0,19,0,0,0,115,38,0, - 0,0,116,0,160,1,124,1,161,1,115,28,116,2,100,1, - 160,3,124,1,161,1,124,1,100,2,141,2,130,1,136,0, - 124,0,124,1,131,2,83,0,41,3,78,122,27,123,33,114, - 125,32,105,115,32,110,111,116,32,97,32,102,114,111,122,101, - 110,32,109,111,100,117,108,101,41,1,114,15,0,0,0,41, - 4,114,49,0,0,0,218,9,105,115,95,102,114,111,122,101, - 110,114,70,0,0,0,114,38,0,0,0,41,2,114,26,0, - 0,0,114,71,0,0,0,41,1,114,72,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,24,95,114,101,113,117,105, - 114,101,115,95,102,114,111,122,101,110,95,119,114,97,112,112, - 101,114,243,0,0,0,115,8,0,0,0,0,1,10,1,10, - 1,8,1,122,50,95,114,101,113,117,105,114,101,115,95,102, - 114,111,122,101,110,46,60,108,111,99,97,108,115,62,46,95, - 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,95, - 119,114,97,112,112,101,114,41,1,114,12,0,0,0,41,2, - 114,72,0,0,0,114,76,0,0,0,114,10,0,0,0,41, - 1,114,72,0,0,0,114,11,0,0,0,218,16,95,114,101, - 113,117,105,114,101,115,95,102,114,111,122,101,110,241,0,0, - 0,115,6,0,0,0,0,2,12,5,10,1,114,77,0,0, - 0,99,2,0,0,0,0,0,0,0,4,0,0,0,3,0, - 0,0,67,0,0,0,115,62,0,0,0,116,0,124,1,124, - 0,131,2,125,2,124,1,116,1,106,2,107,6,114,50,116, - 1,106,2,124,1,25,0,125,3,116,3,124,2,124,3,131, - 2,1,0,116,1,106,2,124,1,25,0,83,0,116,4,124, - 2,131,1,83,0,100,1,83,0,41,2,122,128,76,111,97, - 100,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, - 109,111,100,117,108,101,32,105,110,116,111,32,115,121,115,46, - 109,111,100,117,108,101,115,32,97,110,100,32,114,101,116,117, - 114,110,32,105,116,46,10,10,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,108,111,97,100, - 101,114,46,101,120,101,99,95,109,111,100,117,108,101,32,105, - 110,115,116,101,97,100,46,10,10,32,32,32,32,78,41,5, - 218,16,115,112,101,99,95,102,114,111,109,95,108,111,97,100, - 101,114,114,14,0,0,0,218,7,109,111,100,117,108,101,115, - 218,5,95,101,120,101,99,218,5,95,108,111,97,100,41,4, - 114,26,0,0,0,114,71,0,0,0,218,4,115,112,101,99, - 218,6,109,111,100,117,108,101,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,17,95,108,111,97,100,95,109, - 111,100,117,108,101,95,115,104,105,109,253,0,0,0,115,12, - 0,0,0,0,6,10,1,10,1,10,1,10,1,10,2,114, - 84,0,0,0,99,1,0,0,0,0,0,0,0,5,0,0, - 0,36,0,0,0,67,0,0,0,115,216,0,0,0,116,0, - 124,0,100,1,100,0,131,3,125,1,116,1,124,1,100,2, - 131,2,114,54,121,10,124,1,160,2,124,0,161,1,83,0, - 4,0,116,3,107,10,114,52,1,0,1,0,1,0,89,0, - 110,2,88,0,121,10,124,0,106,4,125,2,87,0,110,20, - 4,0,116,5,107,10,114,84,1,0,1,0,1,0,89,0, - 110,18,88,0,124,2,100,0,107,9,114,102,116,6,124,2, - 131,1,83,0,121,10,124,0,106,7,125,3,87,0,110,24, - 4,0,116,5,107,10,114,136,1,0,1,0,1,0,100,3, - 125,3,89,0,110,2,88,0,121,10,124,0,106,8,125,4, - 87,0,110,50,4,0,116,5,107,10,114,198,1,0,1,0, - 1,0,124,1,100,0,107,8,114,182,100,4,160,9,124,3, - 161,1,83,0,100,5,160,9,124,3,124,1,161,2,83,0, - 89,0,110,14,88,0,100,6,160,9,124,3,124,4,161,2, - 83,0,100,0,83,0,41,7,78,218,10,95,95,108,111,97, - 100,101,114,95,95,218,11,109,111,100,117,108,101,95,114,101, - 112,114,250,1,63,122,13,60,109,111,100,117,108,101,32,123, - 33,114,125,62,122,20,60,109,111,100,117,108,101,32,123,33, - 114,125,32,40,123,33,114,125,41,62,122,23,60,109,111,100, - 117,108,101,32,123,33,114,125,32,102,114,111,109,32,123,33, - 114,125,62,41,10,114,6,0,0,0,114,4,0,0,0,114, - 86,0,0,0,218,9,69,120,99,101,112,116,105,111,110,218, - 8,95,95,115,112,101,99,95,95,218,14,65,116,116,114,105, - 98,117,116,101,69,114,114,111,114,218,22,95,109,111,100,117, - 108,101,95,114,101,112,114,95,102,114,111,109,95,115,112,101, - 99,114,1,0,0,0,218,8,95,95,102,105,108,101,95,95, - 114,38,0,0,0,41,5,114,83,0,0,0,218,6,108,111, - 97,100,101,114,114,82,0,0,0,114,15,0,0,0,218,8, - 102,105,108,101,110,97,109,101,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,12,95,109,111,100,117,108,101, - 95,114,101,112,114,13,1,0,0,115,46,0,0,0,0,2, - 12,1,10,4,2,1,10,1,14,1,6,1,2,1,10,1, - 14,1,6,2,8,1,8,4,2,1,10,1,14,1,10,1, - 2,1,10,1,14,1,8,1,10,2,18,2,114,95,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,64,0,0,0,115,36,0,0,0,101,0,90,1,100, - 0,90,2,100,1,100,2,132,0,90,3,100,3,100,4,132, - 0,90,4,100,5,100,6,132,0,90,5,100,7,83,0,41, - 8,218,17,95,105,110,115,116,97,108,108,101,100,95,115,97, - 102,101,108,121,99,2,0,0,0,0,0,0,0,2,0,0, - 0,2,0,0,0,67,0,0,0,115,18,0,0,0,124,1, - 124,0,95,0,124,1,106,1,124,0,95,2,100,0,83,0, - 41,1,78,41,3,218,7,95,109,111,100,117,108,101,114,89, - 0,0,0,218,5,95,115,112,101,99,41,2,114,26,0,0, - 0,114,83,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,27,0,0,0,51,1,0,0,115,4, - 0,0,0,0,1,6,1,122,26,95,105,110,115,116,97,108, - 108,101,100,95,115,97,102,101,108,121,46,95,95,105,110,105, + 11,0,0,0,114,27,0,0,0,143,0,0,0,115,4,0, + 0,0,0,1,6,1,122,27,95,77,111,100,117,108,101,76, + 111,99,107,77,97,110,97,103,101,114,46,95,95,105,110,105, 116,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,28,0,0,0,100,1,124, - 0,106,0,95,1,124,0,106,2,116,3,106,4,124,0,106, - 0,106,5,60,0,100,0,83,0,41,2,78,84,41,6,114, - 98,0,0,0,218,13,95,105,110,105,116,105,97,108,105,122, - 105,110,103,114,97,0,0,0,114,14,0,0,0,114,79,0, - 0,0,114,15,0,0,0,41,1,114,26,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,46,0, - 0,0,55,1,0,0,115,4,0,0,0,0,4,8,1,122, - 27,95,105,110,115,116,97,108,108,101,100,95,115,97,102,101, - 108,121,46,95,95,101,110,116,101,114,95,95,99,1,0,0, - 0,0,0,0,0,3,0,0,0,17,0,0,0,71,0,0, - 0,115,98,0,0,0,122,82,124,0,106,0,125,2,116,1, - 100,1,100,2,132,0,124,1,68,0,131,1,131,1,114,64, - 121,14,116,2,106,3,124,2,106,4,61,0,87,0,113,80, - 4,0,116,5,107,10,114,60,1,0,1,0,1,0,89,0, - 113,80,88,0,110,16,116,6,100,3,124,2,106,4,124,2, - 106,7,131,3,1,0,87,0,100,0,100,4,124,0,106,0, - 95,8,88,0,100,0,83,0,41,5,78,99,1,0,0,0, - 0,0,0,0,2,0,0,0,3,0,0,0,115,0,0,0, - 115,22,0,0,0,124,0,93,14,125,1,124,1,100,0,107, - 9,86,0,1,0,113,2,100,0,83,0,41,1,78,114,10, - 0,0,0,41,2,90,2,46,48,90,3,97,114,103,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,250,9,60, - 103,101,110,101,120,112,114,62,65,1,0,0,115,2,0,0, - 0,4,0,122,45,95,105,110,115,116,97,108,108,101,100,95, - 115,97,102,101,108,121,46,95,95,101,120,105,116,95,95,46, - 60,108,111,99,97,108,115,62,46,60,103,101,110,101,120,112, - 114,62,122,18,105,109,112,111,114,116,32,123,33,114,125,32, - 35,32,123,33,114,125,70,41,9,114,98,0,0,0,218,3, - 97,110,121,114,14,0,0,0,114,79,0,0,0,114,15,0, - 0,0,114,55,0,0,0,114,68,0,0,0,114,93,0,0, - 0,114,99,0,0,0,41,3,114,26,0,0,0,114,47,0, - 0,0,114,82,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,48,0,0,0,62,1,0,0,115, - 18,0,0,0,0,1,2,1,6,1,18,1,2,1,14,1, - 14,1,8,2,20,2,122,26,95,105,110,115,116,97,108,108, - 101,100,95,115,97,102,101,108,121,46,95,95,101,120,105,116, - 95,95,78,41,6,114,1,0,0,0,114,0,0,0,0,114, - 2,0,0,0,114,27,0,0,0,114,46,0,0,0,114,48, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,96,0,0,0,49,1,0,0, - 115,6,0,0,0,8,2,8,4,8,7,114,96,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,64,0,0,0,115,114,0,0,0,101,0,90,1,100,0, - 90,2,100,1,90,3,100,2,100,2,100,2,100,3,156,3, - 100,4,100,5,132,2,90,4,100,6,100,7,132,0,90,5, - 100,8,100,9,132,0,90,6,101,7,100,10,100,11,132,0, - 131,1,90,8,101,8,106,9,100,12,100,11,132,0,131,1, - 90,8,101,7,100,13,100,14,132,0,131,1,90,10,101,7, - 100,15,100,16,132,0,131,1,90,11,101,11,106,9,100,17, - 100,16,132,0,131,1,90,11,100,2,83,0,41,18,218,10, - 77,111,100,117,108,101,83,112,101,99,97,208,5,0,0,84, - 104,101,32,115,112,101,99,105,102,105,99,97,116,105,111,110, - 32,102,111,114,32,97,32,109,111,100,117,108,101,44,32,117, - 115,101,100,32,102,111,114,32,108,111,97,100,105,110,103,46, - 10,10,32,32,32,32,65,32,109,111,100,117,108,101,39,115, - 32,115,112,101,99,32,105,115,32,116,104,101,32,115,111,117, - 114,99,101,32,102,111,114,32,105,110,102,111,114,109,97,116, - 105,111,110,32,97,98,111,117,116,32,116,104,101,32,109,111, - 100,117,108,101,46,32,32,70,111,114,10,32,32,32,32,100, - 97,116,97,32,97,115,115,111,99,105,97,116,101,100,32,119, - 105,116,104,32,116,104,101,32,109,111,100,117,108,101,44,32, - 105,110,99,108,117,100,105,110,103,32,115,111,117,114,99,101, - 44,32,117,115,101,32,116,104,101,32,115,112,101,99,39,115, - 10,32,32,32,32,108,111,97,100,101,114,46,10,10,32,32, - 32,32,96,110,97,109,101,96,32,105,115,32,116,104,101,32, - 97,98,115,111,108,117,116,101,32,110,97,109,101,32,111,102, - 32,116,104,101,32,109,111,100,117,108,101,46,32,32,96,108, - 111,97,100,101,114,96,32,105,115,32,116,104,101,32,108,111, - 97,100,101,114,10,32,32,32,32,116,111,32,117,115,101,32, - 119,104,101,110,32,108,111,97,100,105,110,103,32,116,104,101, - 32,109,111,100,117,108,101,46,32,32,96,112,97,114,101,110, - 116,96,32,105,115,32,116,104,101,32,110,97,109,101,32,111, - 102,32,116,104,101,10,32,32,32,32,112,97,99,107,97,103, - 101,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, - 105,110,46,32,32,84,104,101,32,112,97,114,101,110,116,32, - 105,115,32,100,101,114,105,118,101,100,32,102,114,111,109,32, - 116,104,101,32,110,97,109,101,46,10,10,32,32,32,32,96, - 105,115,95,112,97,99,107,97,103,101,96,32,100,101,116,101, - 114,109,105,110,101,115,32,105,102,32,116,104,101,32,109,111, - 100,117,108,101,32,105,115,32,99,111,110,115,105,100,101,114, - 101,100,32,97,32,112,97,99,107,97,103,101,32,111,114,10, - 32,32,32,32,110,111,116,46,32,32,79,110,32,109,111,100, - 117,108,101,115,32,116,104,105,115,32,105,115,32,114,101,102, - 108,101,99,116,101,100,32,98,121,32,116,104,101,32,96,95, - 95,112,97,116,104,95,95,96,32,97,116,116,114,105,98,117, - 116,101,46,10,10,32,32,32,32,96,111,114,105,103,105,110, - 96,32,105,115,32,116,104,101,32,115,112,101,99,105,102,105, - 99,32,108,111,99,97,116,105,111,110,32,117,115,101,100,32, - 98,121,32,116,104,101,32,108,111,97,100,101,114,32,102,114, - 111,109,32,119,104,105,99,104,32,116,111,10,32,32,32,32, - 108,111,97,100,32,116,104,101,32,109,111,100,117,108,101,44, - 32,105,102,32,116,104,97,116,32,105,110,102,111,114,109,97, - 116,105,111,110,32,105,115,32,97,118,97,105,108,97,98,108, - 101,46,32,32,87,104,101,110,32,102,105,108,101,110,97,109, - 101,32,105,115,10,32,32,32,32,115,101,116,44,32,111,114, - 105,103,105,110,32,119,105,108,108,32,109,97,116,99,104,46, - 10,10,32,32,32,32,96,104,97,115,95,108,111,99,97,116, - 105,111,110,96,32,105,110,100,105,99,97,116,101,115,32,116, - 104,97,116,32,97,32,115,112,101,99,39,115,32,34,111,114, - 105,103,105,110,34,32,114,101,102,108,101,99,116,115,32,97, - 32,108,111,99,97,116,105,111,110,46,10,32,32,32,32,87, - 104,101,110,32,116,104,105,115,32,105,115,32,84,114,117,101, - 44,32,96,95,95,102,105,108,101,95,95,96,32,97,116,116, - 114,105,98,117,116,101,32,111,102,32,116,104,101,32,109,111, - 100,117,108,101,32,105,115,32,115,101,116,46,10,10,32,32, - 32,32,96,99,97,99,104,101,100,96,32,105,115,32,116,104, - 101,32,108,111,99,97,116,105,111,110,32,111,102,32,116,104, - 101,32,99,97,99,104,101,100,32,98,121,116,101,99,111,100, - 101,32,102,105,108,101,44,32,105,102,32,97,110,121,46,32, - 32,73,116,10,32,32,32,32,99,111,114,114,101,115,112,111, - 110,100,115,32,116,111,32,116,104,101,32,96,95,95,99,97, - 99,104,101,100,95,95,96,32,97,116,116,114,105,98,117,116, - 101,46,10,10,32,32,32,32,96,115,117,98,109,111,100,117, - 108,101,95,115,101,97,114,99,104,95,108,111,99,97,116,105, - 111,110,115,96,32,105,115,32,116,104,101,32,115,101,113,117, - 101,110,99,101,32,111,102,32,112,97,116,104,32,101,110,116, - 114,105,101,115,32,116,111,10,32,32,32,32,115,101,97,114, - 99,104,32,119,104,101,110,32,105,109,112,111,114,116,105,110, - 103,32,115,117,98,109,111,100,117,108,101,115,46,32,32,73, - 102,32,115,101,116,44,32,105,115,95,112,97,99,107,97,103, - 101,32,115,104,111,117,108,100,32,98,101,10,32,32,32,32, - 84,114,117,101,45,45,97,110,100,32,70,97,108,115,101,32, - 111,116,104,101,114,119,105,115,101,46,10,10,32,32,32,32, - 80,97,99,107,97,103,101,115,32,97,114,101,32,115,105,109, - 112,108,121,32,109,111,100,117,108,101,115,32,116,104,97,116, - 32,40,109,97,121,41,32,104,97,118,101,32,115,117,98,109, - 111,100,117,108,101,115,46,32,32,73,102,32,97,32,115,112, - 101,99,10,32,32,32,32,104,97,115,32,97,32,110,111,110, - 45,78,111,110,101,32,118,97,108,117,101,32,105,110,32,96, - 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, - 95,108,111,99,97,116,105,111,110,115,96,44,32,116,104,101, - 32,105,109,112,111,114,116,10,32,32,32,32,115,121,115,116, - 101,109,32,119,105,108,108,32,99,111,110,115,105,100,101,114, - 32,109,111,100,117,108,101,115,32,108,111,97,100,101,100,32, - 102,114,111,109,32,116,104,101,32,115,112,101,99,32,97,115, - 32,112,97,99,107,97,103,101,115,46,10,10,32,32,32,32, - 79,110,108,121,32,102,105,110,100,101,114,115,32,40,115,101, - 101,32,105,109,112,111,114,116,108,105,98,46,97,98,99,46, - 77,101,116,97,80,97,116,104,70,105,110,100,101,114,32,97, - 110,100,10,32,32,32,32,105,109,112,111,114,116,108,105,98, - 46,97,98,99,46,80,97,116,104,69,110,116,114,121,70,105, - 110,100,101,114,41,32,115,104,111,117,108,100,32,109,111,100, - 105,102,121,32,77,111,100,117,108,101,83,112,101,99,32,105, - 110,115,116,97,110,99,101,115,46,10,10,32,32,32,32,78, - 41,3,218,6,111,114,105,103,105,110,218,12,108,111,97,100, - 101,114,95,115,116,97,116,101,218,10,105,115,95,112,97,99, - 107,97,103,101,99,3,0,0,0,3,0,0,0,6,0,0, - 0,2,0,0,0,67,0,0,0,115,54,0,0,0,124,1, - 124,0,95,0,124,2,124,0,95,1,124,3,124,0,95,2, - 124,4,124,0,95,3,124,5,114,32,103,0,110,2,100,0, - 124,0,95,4,100,1,124,0,95,5,100,0,124,0,95,6, - 100,0,83,0,41,2,78,70,41,7,114,15,0,0,0,114, - 93,0,0,0,114,103,0,0,0,114,104,0,0,0,218,26, - 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, - 95,108,111,99,97,116,105,111,110,115,218,13,95,115,101,116, - 95,102,105,108,101,97,116,116,114,218,7,95,99,97,99,104, - 101,100,41,6,114,26,0,0,0,114,15,0,0,0,114,93, - 0,0,0,114,103,0,0,0,114,104,0,0,0,114,105,0, + 2,0,0,0,67,0,0,0,115,26,0,0,0,116,0,124, + 0,106,1,131,1,124,0,95,2,124,0,106,2,160,3,161, + 0,1,0,100,0,83,0,41,1,78,41,4,218,16,95,103, + 101,116,95,109,111,100,117,108,101,95,108,111,99,107,114,43, + 0,0,0,114,44,0,0,0,114,34,0,0,0,41,1,114, + 26,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,9,95,95,101,110,116,101,114,95,95,147,0, + 0,0,115,4,0,0,0,0,1,12,1,122,28,95,77,111, + 100,117,108,101,76,111,99,107,77,97,110,97,103,101,114,46, + 95,95,101,110,116,101,114,95,95,99,1,0,0,0,0,0, + 0,0,3,0,0,0,2,0,0,0,79,0,0,0,115,14, + 0,0,0,124,0,106,0,160,1,161,0,1,0,100,0,83, + 0,41,1,78,41,2,114,44,0,0,0,114,35,0,0,0, + 41,3,114,26,0,0,0,218,4,97,114,103,115,90,6,107, + 119,97,114,103,115,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,8,95,95,101,120,105,116,95,95,151,0, + 0,0,115,2,0,0,0,0,1,122,27,95,77,111,100,117, + 108,101,76,111,99,107,77,97,110,97,103,101,114,46,95,95, + 101,120,105,116,95,95,78,41,6,114,1,0,0,0,114,0, + 0,0,0,114,2,0,0,0,114,27,0,0,0,114,46,0, + 0,0,114,48,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,42,0,0,0, + 141,0,0,0,115,6,0,0,0,8,2,8,4,8,4,114, + 42,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0, + 0,18,0,0,0,67,0,0,0,115,130,0,0,0,116,0, + 160,1,161,0,1,0,122,106,121,14,116,2,124,0,25,0, + 131,0,125,1,87,0,110,24,4,0,116,3,107,10,114,48, + 1,0,1,0,1,0,100,1,125,1,89,0,110,2,88,0, + 124,1,100,1,107,8,114,112,116,4,100,1,107,8,114,76, + 116,5,124,0,131,1,125,1,110,8,116,6,124,0,131,1, + 125,1,124,0,102,1,100,2,100,3,132,1,125,2,116,7, + 160,8,124,1,124,2,161,2,116,2,124,0,60,0,87,0, + 100,1,116,0,160,9,161,0,1,0,88,0,124,1,83,0, + 41,4,122,139,71,101,116,32,111,114,32,99,114,101,97,116, + 101,32,116,104,101,32,109,111,100,117,108,101,32,108,111,99, + 107,32,102,111,114,32,97,32,103,105,118,101,110,32,109,111, + 100,117,108,101,32,110,97,109,101,46,10,10,32,32,32,32, + 65,99,113,117,105,114,101,47,114,101,108,101,97,115,101,32, + 105,110,116,101,114,110,97,108,108,121,32,116,104,101,32,103, + 108,111,98,97,108,32,105,109,112,111,114,116,32,108,111,99, + 107,32,116,111,32,112,114,111,116,101,99,116,10,32,32,32, + 32,95,109,111,100,117,108,101,95,108,111,99,107,115,46,78, + 99,2,0,0,0,0,0,0,0,2,0,0,0,11,0,0, + 0,83,0,0,0,115,48,0,0,0,116,0,160,1,161,0, + 1,0,122,24,116,2,160,3,124,1,161,1,124,0,107,8, + 114,30,116,2,124,1,61,0,87,0,100,0,116,0,160,4, + 161,0,1,0,88,0,100,0,83,0,41,1,78,41,5,218, + 4,95,105,109,112,218,12,97,99,113,117,105,114,101,95,108, + 111,99,107,218,13,95,109,111,100,117,108,101,95,108,111,99, + 107,115,114,30,0,0,0,218,12,114,101,108,101,97,115,101, + 95,108,111,99,107,41,2,218,3,114,101,102,114,15,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,2,99,98,176,0,0,0,115,10,0,0,0,0,1,8, + 1,2,4,14,1,10,2,122,28,95,103,101,116,95,109,111, + 100,117,108,101,95,108,111,99,107,46,60,108,111,99,97,108, + 115,62,46,99,98,41,10,114,49,0,0,0,114,50,0,0, + 0,114,51,0,0,0,218,8,75,101,121,69,114,114,111,114, + 114,20,0,0,0,114,41,0,0,0,114,18,0,0,0,218, + 8,95,119,101,97,107,114,101,102,114,53,0,0,0,114,52, + 0,0,0,41,3,114,15,0,0,0,114,21,0,0,0,114, + 54,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,45,0,0,0,157,0,0,0,115,28,0,0, + 0,0,6,8,1,2,1,2,1,14,1,14,1,10,2,8, + 1,8,1,10,2,8,2,12,11,20,2,10,2,114,45,0, + 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,11, + 0,0,0,67,0,0,0,115,54,0,0,0,116,0,124,0, + 131,1,125,1,121,12,124,1,160,1,161,0,1,0,87,0, + 110,20,4,0,116,2,107,10,114,40,1,0,1,0,1,0, + 89,0,110,10,88,0,124,1,160,3,161,0,1,0,100,1, + 83,0,41,2,122,189,65,99,113,117,105,114,101,115,32,116, + 104,101,110,32,114,101,108,101,97,115,101,115,32,116,104,101, + 32,109,111,100,117,108,101,32,108,111,99,107,32,102,111,114, + 32,97,32,103,105,118,101,110,32,109,111,100,117,108,101,32, + 110,97,109,101,46,10,10,32,32,32,32,84,104,105,115,32, + 105,115,32,117,115,101,100,32,116,111,32,101,110,115,117,114, + 101,32,97,32,109,111,100,117,108,101,32,105,115,32,99,111, + 109,112,108,101,116,101,108,121,32,105,110,105,116,105,97,108, + 105,122,101,100,44,32,105,110,32,116,104,101,10,32,32,32, + 32,101,118,101,110,116,32,105,116,32,105,115,32,98,101,105, + 110,103,32,105,109,112,111,114,116,101,100,32,98,121,32,97, + 110,111,116,104,101,114,32,116,104,114,101,97,100,46,10,32, + 32,32,32,78,41,4,114,45,0,0,0,114,34,0,0,0, + 114,17,0,0,0,114,35,0,0,0,41,2,114,15,0,0, + 0,114,21,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,19,95,108,111,99,107,95,117,110,108, + 111,99,107,95,109,111,100,117,108,101,194,0,0,0,115,12, + 0,0,0,0,6,8,1,2,1,12,1,14,3,6,2,114, + 57,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,79,0,0,0,115,10,0,0,0,124,0, + 124,1,124,2,142,1,83,0,41,1,97,46,1,0,0,114, + 101,109,111,118,101,95,105,109,112,111,114,116,108,105,98,95, + 102,114,97,109,101,115,32,105,110,32,105,109,112,111,114,116, + 46,99,32,119,105,108,108,32,97,108,119,97,121,115,32,114, + 101,109,111,118,101,32,115,101,113,117,101,110,99,101,115,10, + 32,32,32,32,111,102,32,105,109,112,111,114,116,108,105,98, + 32,102,114,97,109,101,115,32,116,104,97,116,32,101,110,100, + 32,119,105,116,104,32,97,32,99,97,108,108,32,116,111,32, + 116,104,105,115,32,102,117,110,99,116,105,111,110,10,10,32, + 32,32,32,85,115,101,32,105,116,32,105,110,115,116,101,97, + 100,32,111,102,32,97,32,110,111,114,109,97,108,32,99,97, + 108,108,32,105,110,32,112,108,97,99,101,115,32,119,104,101, + 114,101,32,105,110,99,108,117,100,105,110,103,32,116,104,101, + 32,105,109,112,111,114,116,108,105,98,10,32,32,32,32,102, + 114,97,109,101,115,32,105,110,116,114,111,100,117,99,101,115, + 32,117,110,119,97,110,116,101,100,32,110,111,105,115,101,32, + 105,110,116,111,32,116,104,101,32,116,114,97,99,101,98,97, + 99,107,32,40,101,46,103,46,32,119,104,101,110,32,101,120, + 101,99,117,116,105,110,103,10,32,32,32,32,109,111,100,117, + 108,101,32,99,111,100,101,41,10,32,32,32,32,114,10,0, + 0,0,41,3,218,1,102,114,47,0,0,0,90,4,107,119, + 100,115,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,218,25,95,99,97,108,108,95,119,105,116,104,95,102,114, + 97,109,101,115,95,114,101,109,111,118,101,100,211,0,0,0, + 115,2,0,0,0,0,8,114,59,0,0,0,114,33,0,0, + 0,41,1,218,9,118,101,114,98,111,115,105,116,121,99,1, + 0,0,0,1,0,0,0,3,0,0,0,4,0,0,0,71, + 0,0,0,115,54,0,0,0,116,0,106,1,106,2,124,1, + 107,5,114,50,124,0,160,3,100,1,161,1,115,30,100,2, + 124,0,23,0,125,0,116,4,124,0,106,5,124,2,142,0, + 116,0,106,6,100,3,141,2,1,0,100,4,83,0,41,5, + 122,61,80,114,105,110,116,32,116,104,101,32,109,101,115,115, + 97,103,101,32,116,111,32,115,116,100,101,114,114,32,105,102, + 32,45,118,47,80,89,84,72,79,78,86,69,82,66,79,83, + 69,32,105,115,32,116,117,114,110,101,100,32,111,110,46,41, + 2,250,1,35,122,7,105,109,112,111,114,116,32,122,2,35, + 32,41,1,90,4,102,105,108,101,78,41,7,114,14,0,0, + 0,218,5,102,108,97,103,115,218,7,118,101,114,98,111,115, + 101,218,10,115,116,97,114,116,115,119,105,116,104,218,5,112, + 114,105,110,116,114,38,0,0,0,218,6,115,116,100,101,114, + 114,41,3,218,7,109,101,115,115,97,103,101,114,60,0,0, + 0,114,47,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,16,95,118,101,114,98,111,115,101,95, + 109,101,115,115,97,103,101,222,0,0,0,115,8,0,0,0, + 0,2,12,1,10,1,8,1,114,68,0,0,0,99,1,0, + 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, + 0,0,115,26,0,0,0,135,0,102,1,100,1,100,2,132, + 8,125,1,116,0,124,1,136,0,131,2,1,0,124,1,83, + 0,41,3,122,49,68,101,99,111,114,97,116,111,114,32,116, + 111,32,118,101,114,105,102,121,32,116,104,101,32,110,97,109, + 101,100,32,109,111,100,117,108,101,32,105,115,32,98,117,105, + 108,116,45,105,110,46,99,2,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,19,0,0,0,115,38,0,0,0, + 124,1,116,0,106,1,107,7,114,28,116,2,100,1,160,3, + 124,1,161,1,124,1,100,2,141,2,130,1,136,0,124,0, + 124,1,131,2,83,0,41,3,78,122,29,123,33,114,125,32, + 105,115,32,110,111,116,32,97,32,98,117,105,108,116,45,105, + 110,32,109,111,100,117,108,101,41,1,114,15,0,0,0,41, + 4,114,14,0,0,0,218,20,98,117,105,108,116,105,110,95, + 109,111,100,117,108,101,95,110,97,109,101,115,218,11,73,109, + 112,111,114,116,69,114,114,111,114,114,38,0,0,0,41,2, + 114,26,0,0,0,218,8,102,117,108,108,110,97,109,101,41, + 1,218,3,102,120,110,114,10,0,0,0,114,11,0,0,0, + 218,25,95,114,101,113,117,105,114,101,115,95,98,117,105,108, + 116,105,110,95,119,114,97,112,112,101,114,232,0,0,0,115, + 8,0,0,0,0,1,10,1,10,1,8,1,122,52,95,114, + 101,113,117,105,114,101,115,95,98,117,105,108,116,105,110,46, + 60,108,111,99,97,108,115,62,46,95,114,101,113,117,105,114, + 101,115,95,98,117,105,108,116,105,110,95,119,114,97,112,112, + 101,114,41,1,114,12,0,0,0,41,2,114,72,0,0,0, + 114,73,0,0,0,114,10,0,0,0,41,1,114,72,0,0, + 0,114,11,0,0,0,218,17,95,114,101,113,117,105,114,101, + 115,95,98,117,105,108,116,105,110,230,0,0,0,115,6,0, + 0,0,0,2,12,5,10,1,114,74,0,0,0,99,1,0, + 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, + 0,0,115,26,0,0,0,135,0,102,1,100,1,100,2,132, + 8,125,1,116,0,124,1,136,0,131,2,1,0,124,1,83, + 0,41,3,122,47,68,101,99,111,114,97,116,111,114,32,116, + 111,32,118,101,114,105,102,121,32,116,104,101,32,110,97,109, + 101,100,32,109,111,100,117,108,101,32,105,115,32,102,114,111, + 122,101,110,46,99,2,0,0,0,0,0,0,0,2,0,0, + 0,4,0,0,0,19,0,0,0,115,38,0,0,0,116,0, + 160,1,124,1,161,1,115,28,116,2,100,1,160,3,124,1, + 161,1,124,1,100,2,141,2,130,1,136,0,124,0,124,1, + 131,2,83,0,41,3,78,122,27,123,33,114,125,32,105,115, + 32,110,111,116,32,97,32,102,114,111,122,101,110,32,109,111, + 100,117,108,101,41,1,114,15,0,0,0,41,4,114,49,0, + 0,0,218,9,105,115,95,102,114,111,122,101,110,114,70,0, + 0,0,114,38,0,0,0,41,2,114,26,0,0,0,114,71, + 0,0,0,41,1,114,72,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,24,95,114,101,113,117,105,114,101,115,95, + 102,114,111,122,101,110,95,119,114,97,112,112,101,114,243,0, + 0,0,115,8,0,0,0,0,1,10,1,10,1,8,1,122, + 50,95,114,101,113,117,105,114,101,115,95,102,114,111,122,101, + 110,46,60,108,111,99,97,108,115,62,46,95,114,101,113,117, + 105,114,101,115,95,102,114,111,122,101,110,95,119,114,97,112, + 112,101,114,41,1,114,12,0,0,0,41,2,114,72,0,0, + 0,114,76,0,0,0,114,10,0,0,0,41,1,114,72,0, + 0,0,114,11,0,0,0,218,16,95,114,101,113,117,105,114, + 101,115,95,102,114,111,122,101,110,241,0,0,0,115,6,0, + 0,0,0,2,12,5,10,1,114,77,0,0,0,99,2,0, + 0,0,0,0,0,0,4,0,0,0,3,0,0,0,67,0, + 0,0,115,62,0,0,0,116,0,124,1,124,0,131,2,125, + 2,124,1,116,1,106,2,107,6,114,50,116,1,106,2,124, + 1,25,0,125,3,116,3,124,2,124,3,131,2,1,0,116, + 1,106,2,124,1,25,0,83,0,116,4,124,2,131,1,83, + 0,100,1,83,0,41,2,122,128,76,111,97,100,32,116,104, + 101,32,115,112,101,99,105,102,105,101,100,32,109,111,100,117, + 108,101,32,105,110,116,111,32,115,121,115,46,109,111,100,117, + 108,101,115,32,97,110,100,32,114,101,116,117,114,110,32,105, + 116,46,10,10,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,85,115,101,32,108,111,97,100,101,114,46,101, + 120,101,99,95,109,111,100,117,108,101,32,105,110,115,116,101, + 97,100,46,10,10,32,32,32,32,78,41,5,218,16,115,112, + 101,99,95,102,114,111,109,95,108,111,97,100,101,114,114,14, + 0,0,0,218,7,109,111,100,117,108,101,115,218,5,95,101, + 120,101,99,218,5,95,108,111,97,100,41,4,114,26,0,0, + 0,114,71,0,0,0,218,4,115,112,101,99,218,6,109,111, + 100,117,108,101,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,17,95,108,111,97,100,95,109,111,100,117,108, + 101,95,115,104,105,109,253,0,0,0,115,12,0,0,0,0, + 6,10,1,10,1,10,1,10,1,10,2,114,84,0,0,0, + 99,1,0,0,0,0,0,0,0,5,0,0,0,36,0,0, + 0,67,0,0,0,115,216,0,0,0,116,0,124,0,100,1, + 100,0,131,3,125,1,116,1,124,1,100,2,131,2,114,54, + 121,10,124,1,160,2,124,0,161,1,83,0,4,0,116,3, + 107,10,114,52,1,0,1,0,1,0,89,0,110,2,88,0, + 121,10,124,0,106,4,125,2,87,0,110,20,4,0,116,5, + 107,10,114,84,1,0,1,0,1,0,89,0,110,18,88,0, + 124,2,100,0,107,9,114,102,116,6,124,2,131,1,83,0, + 121,10,124,0,106,7,125,3,87,0,110,24,4,0,116,5, + 107,10,114,136,1,0,1,0,1,0,100,3,125,3,89,0, + 110,2,88,0,121,10,124,0,106,8,125,4,87,0,110,50, + 4,0,116,5,107,10,114,198,1,0,1,0,1,0,124,1, + 100,0,107,8,114,182,100,4,160,9,124,3,161,1,83,0, + 100,5,160,9,124,3,124,1,161,2,83,0,89,0,110,14, + 88,0,100,6,160,9,124,3,124,4,161,2,83,0,100,0, + 83,0,41,7,78,218,10,95,95,108,111,97,100,101,114,95, + 95,218,11,109,111,100,117,108,101,95,114,101,112,114,250,1, + 63,122,13,60,109,111,100,117,108,101,32,123,33,114,125,62, + 122,20,60,109,111,100,117,108,101,32,123,33,114,125,32,40, + 123,33,114,125,41,62,122,23,60,109,111,100,117,108,101,32, + 123,33,114,125,32,102,114,111,109,32,123,33,114,125,62,41, + 10,114,6,0,0,0,114,4,0,0,0,114,86,0,0,0, + 218,9,69,120,99,101,112,116,105,111,110,218,8,95,95,115, + 112,101,99,95,95,218,14,65,116,116,114,105,98,117,116,101, + 69,114,114,111,114,218,22,95,109,111,100,117,108,101,95,114, + 101,112,114,95,102,114,111,109,95,115,112,101,99,114,1,0, + 0,0,218,8,95,95,102,105,108,101,95,95,114,38,0,0, + 0,41,5,114,83,0,0,0,218,6,108,111,97,100,101,114, + 114,82,0,0,0,114,15,0,0,0,218,8,102,105,108,101, + 110,97,109,101,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,12,95,109,111,100,117,108,101,95,114,101,112, + 114,13,1,0,0,115,46,0,0,0,0,2,12,1,10,4, + 2,1,10,1,14,1,6,1,2,1,10,1,14,1,6,2, + 8,1,8,4,2,1,10,1,14,1,10,1,2,1,10,1, + 14,1,8,1,10,2,18,2,114,95,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, + 0,0,115,36,0,0,0,101,0,90,1,100,0,90,2,100, + 1,100,2,132,0,90,3,100,3,100,4,132,0,90,4,100, + 5,100,6,132,0,90,5,100,7,83,0,41,8,218,17,95, + 105,110,115,116,97,108,108,101,100,95,115,97,102,101,108,121, + 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, + 0,67,0,0,0,115,18,0,0,0,124,1,124,0,95,0, + 124,1,106,1,124,0,95,2,100,0,83,0,41,1,78,41, + 3,218,7,95,109,111,100,117,108,101,114,89,0,0,0,218, + 5,95,115,112,101,99,41,2,114,26,0,0,0,114,83,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,27,0,0,0,113,1,0,0,115,14,0,0,0,0, - 2,6,1,6,1,6,1,6,1,14,3,6,1,122,19,77, - 111,100,117,108,101,83,112,101,99,46,95,95,105,110,105,116, - 95,95,99,1,0,0,0,0,0,0,0,2,0,0,0,6, - 0,0,0,67,0,0,0,115,102,0,0,0,100,1,160,0, - 124,0,106,1,161,1,100,2,160,0,124,0,106,2,161,1, - 103,2,125,1,124,0,106,3,100,0,107,9,114,52,124,1, - 160,4,100,3,160,0,124,0,106,3,161,1,161,1,1,0, - 124,0,106,5,100,0,107,9,114,80,124,1,160,4,100,4, - 160,0,124,0,106,5,161,1,161,1,1,0,100,5,160,0, - 124,0,106,6,106,7,100,6,160,8,124,1,161,1,161,2, - 83,0,41,7,78,122,9,110,97,109,101,61,123,33,114,125, - 122,11,108,111,97,100,101,114,61,123,33,114,125,122,11,111, - 114,105,103,105,110,61,123,33,114,125,122,29,115,117,98,109, + 0,114,27,0,0,0,51,1,0,0,115,4,0,0,0,0, + 1,6,1,122,26,95,105,110,115,116,97,108,108,101,100,95, + 115,97,102,101,108,121,46,95,95,105,110,105,116,95,95,99, + 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,115,28,0,0,0,100,1,124,0,106,0,95, + 1,124,0,106,2,116,3,106,4,124,0,106,0,106,5,60, + 0,100,0,83,0,41,2,78,84,41,6,114,98,0,0,0, + 218,13,95,105,110,105,116,105,97,108,105,122,105,110,103,114, + 97,0,0,0,114,14,0,0,0,114,79,0,0,0,114,15, + 0,0,0,41,1,114,26,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,46,0,0,0,55,1, + 0,0,115,4,0,0,0,0,4,8,1,122,27,95,105,110, + 115,116,97,108,108,101,100,95,115,97,102,101,108,121,46,95, + 95,101,110,116,101,114,95,95,99,1,0,0,0,0,0,0, + 0,3,0,0,0,17,0,0,0,71,0,0,0,115,98,0, + 0,0,122,82,124,0,106,0,125,2,116,1,100,1,100,2, + 132,0,124,1,68,0,131,1,131,1,114,64,121,14,116,2, + 106,3,124,2,106,4,61,0,87,0,113,80,4,0,116,5, + 107,10,114,60,1,0,1,0,1,0,89,0,113,80,88,0, + 110,16,116,6,100,3,124,2,106,4,124,2,106,7,131,3, + 1,0,87,0,100,0,100,4,124,0,106,0,95,8,88,0, + 100,0,83,0,41,5,78,99,1,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,115,0,0,0,115,22,0,0, + 0,124,0,93,14,125,1,124,1,100,0,107,9,86,0,1, + 0,113,2,100,0,83,0,41,1,78,114,10,0,0,0,41, + 2,90,2,46,48,90,3,97,114,103,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,250,9,60,103,101,110,101, + 120,112,114,62,65,1,0,0,115,2,0,0,0,4,0,122, + 45,95,105,110,115,116,97,108,108,101,100,95,115,97,102,101, + 108,121,46,95,95,101,120,105,116,95,95,46,60,108,111,99, + 97,108,115,62,46,60,103,101,110,101,120,112,114,62,122,18, + 105,109,112,111,114,116,32,123,33,114,125,32,35,32,123,33, + 114,125,70,41,9,114,98,0,0,0,218,3,97,110,121,114, + 14,0,0,0,114,79,0,0,0,114,15,0,0,0,114,55, + 0,0,0,114,68,0,0,0,114,93,0,0,0,114,99,0, + 0,0,41,3,114,26,0,0,0,114,47,0,0,0,114,82, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,48,0,0,0,62,1,0,0,115,18,0,0,0, + 0,1,2,1,6,1,18,1,2,1,14,1,14,1,8,2, + 20,2,122,26,95,105,110,115,116,97,108,108,101,100,95,115, + 97,102,101,108,121,46,95,95,101,120,105,116,95,95,78,41, + 6,114,1,0,0,0,114,0,0,0,0,114,2,0,0,0, + 114,27,0,0,0,114,46,0,0,0,114,48,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,96,0,0,0,49,1,0,0,115,6,0,0, + 0,8,2,8,4,8,7,114,96,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,4,0,0,0,64,0,0, + 0,115,114,0,0,0,101,0,90,1,100,0,90,2,100,1, + 90,3,100,2,100,2,100,2,100,3,156,3,100,4,100,5, + 132,2,90,4,100,6,100,7,132,0,90,5,100,8,100,9, + 132,0,90,6,101,7,100,10,100,11,132,0,131,1,90,8, + 101,8,106,9,100,12,100,11,132,0,131,1,90,8,101,7, + 100,13,100,14,132,0,131,1,90,10,101,7,100,15,100,16, + 132,0,131,1,90,11,101,11,106,9,100,17,100,16,132,0, + 131,1,90,11,100,2,83,0,41,18,218,10,77,111,100,117, + 108,101,83,112,101,99,97,208,5,0,0,84,104,101,32,115, + 112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114, + 32,97,32,109,111,100,117,108,101,44,32,117,115,101,100,32, + 102,111,114,32,108,111,97,100,105,110,103,46,10,10,32,32, + 32,32,65,32,109,111,100,117,108,101,39,115,32,115,112,101, + 99,32,105,115,32,116,104,101,32,115,111,117,114,99,101,32, + 102,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32, + 97,98,111,117,116,32,116,104,101,32,109,111,100,117,108,101, + 46,32,32,70,111,114,10,32,32,32,32,100,97,116,97,32, + 97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32, + 116,104,101,32,109,111,100,117,108,101,44,32,105,110,99,108, + 117,100,105,110,103,32,115,111,117,114,99,101,44,32,117,115, + 101,32,116,104,101,32,115,112,101,99,39,115,10,32,32,32, + 32,108,111,97,100,101,114,46,10,10,32,32,32,32,96,110, + 97,109,101,96,32,105,115,32,116,104,101,32,97,98,115,111, + 108,117,116,101,32,110,97,109,101,32,111,102,32,116,104,101, + 32,109,111,100,117,108,101,46,32,32,96,108,111,97,100,101, + 114,96,32,105,115,32,116,104,101,32,108,111,97,100,101,114, + 10,32,32,32,32,116,111,32,117,115,101,32,119,104,101,110, + 32,108,111,97,100,105,110,103,32,116,104,101,32,109,111,100, + 117,108,101,46,32,32,96,112,97,114,101,110,116,96,32,105, + 115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104, + 101,10,32,32,32,32,112,97,99,107,97,103,101,32,116,104, + 101,32,109,111,100,117,108,101,32,105,115,32,105,110,46,32, + 32,84,104,101,32,112,97,114,101,110,116,32,105,115,32,100, + 101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32, + 110,97,109,101,46,10,10,32,32,32,32,96,105,115,95,112, + 97,99,107,97,103,101,96,32,100,101,116,101,114,109,105,110, + 101,115,32,105,102,32,116,104,101,32,109,111,100,117,108,101, + 32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97, + 32,112,97,99,107,97,103,101,32,111,114,10,32,32,32,32, + 110,111,116,46,32,32,79,110,32,109,111,100,117,108,101,115, + 32,116,104,105,115,32,105,115,32,114,101,102,108,101,99,116, + 101,100,32,98,121,32,116,104,101,32,96,95,95,112,97,116, + 104,95,95,96,32,97,116,116,114,105,98,117,116,101,46,10, + 10,32,32,32,32,96,111,114,105,103,105,110,96,32,105,115, + 32,116,104,101,32,115,112,101,99,105,102,105,99,32,108,111, + 99,97,116,105,111,110,32,117,115,101,100,32,98,121,32,116, + 104,101,32,108,111,97,100,101,114,32,102,114,111,109,32,119, + 104,105,99,104,32,116,111,10,32,32,32,32,108,111,97,100, + 32,116,104,101,32,109,111,100,117,108,101,44,32,105,102,32, + 116,104,97,116,32,105,110,102,111,114,109,97,116,105,111,110, + 32,105,115,32,97,118,97,105,108,97,98,108,101,46,32,32, + 87,104,101,110,32,102,105,108,101,110,97,109,101,32,105,115, + 10,32,32,32,32,115,101,116,44,32,111,114,105,103,105,110, + 32,119,105,108,108,32,109,97,116,99,104,46,10,10,32,32, + 32,32,96,104,97,115,95,108,111,99,97,116,105,111,110,96, + 32,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32, + 97,32,115,112,101,99,39,115,32,34,111,114,105,103,105,110, + 34,32,114,101,102,108,101,99,116,115,32,97,32,108,111,99, + 97,116,105,111,110,46,10,32,32,32,32,87,104,101,110,32, + 116,104,105,115,32,105,115,32,84,114,117,101,44,32,96,95, + 95,102,105,108,101,95,95,96,32,97,116,116,114,105,98,117, + 116,101,32,111,102,32,116,104,101,32,109,111,100,117,108,101, + 32,105,115,32,115,101,116,46,10,10,32,32,32,32,96,99, + 97,99,104,101,100,96,32,105,115,32,116,104,101,32,108,111, + 99,97,116,105,111,110,32,111,102,32,116,104,101,32,99,97, + 99,104,101,100,32,98,121,116,101,99,111,100,101,32,102,105, + 108,101,44,32,105,102,32,97,110,121,46,32,32,73,116,10, + 32,32,32,32,99,111,114,114,101,115,112,111,110,100,115,32, + 116,111,32,116,104,101,32,96,95,95,99,97,99,104,101,100, + 95,95,96,32,97,116,116,114,105,98,117,116,101,46,10,10, + 32,32,32,32,96,115,117,98,109,111,100,117,108,101,95,115, + 101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,96, + 32,105,115,32,116,104,101,32,115,101,113,117,101,110,99,101, + 32,111,102,32,112,97,116,104,32,101,110,116,114,105,101,115, + 32,116,111,10,32,32,32,32,115,101,97,114,99,104,32,119, + 104,101,110,32,105,109,112,111,114,116,105,110,103,32,115,117, + 98,109,111,100,117,108,101,115,46,32,32,73,102,32,115,101, + 116,44,32,105,115,95,112,97,99,107,97,103,101,32,115,104, + 111,117,108,100,32,98,101,10,32,32,32,32,84,114,117,101, + 45,45,97,110,100,32,70,97,108,115,101,32,111,116,104,101, + 114,119,105,115,101,46,10,10,32,32,32,32,80,97,99,107, + 97,103,101,115,32,97,114,101,32,115,105,109,112,108,121,32, + 109,111,100,117,108,101,115,32,116,104,97,116,32,40,109,97, + 121,41,32,104,97,118,101,32,115,117,98,109,111,100,117,108, + 101,115,46,32,32,73,102,32,97,32,115,112,101,99,10,32, + 32,32,32,104,97,115,32,97,32,110,111,110,45,78,111,110, + 101,32,118,97,108,117,101,32,105,110,32,96,115,117,98,109, 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, - 97,116,105,111,110,115,61,123,125,122,6,123,125,40,123,125, - 41,122,2,44,32,41,9,114,38,0,0,0,114,15,0,0, - 0,114,93,0,0,0,114,103,0,0,0,218,6,97,112,112, - 101,110,100,114,106,0,0,0,218,9,95,95,99,108,97,115, - 115,95,95,114,1,0,0,0,218,4,106,111,105,110,41,2, - 114,26,0,0,0,114,47,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,40,0,0,0,125,1, - 0,0,115,16,0,0,0,0,1,10,1,14,1,10,1,18, - 1,10,1,8,1,10,1,122,19,77,111,100,117,108,101,83, - 112,101,99,46,95,95,114,101,112,114,95,95,99,2,0,0, - 0,0,0,0,0,3,0,0,0,11,0,0,0,67,0,0, - 0,115,102,0,0,0,124,0,106,0,125,2,121,70,124,0, - 106,1,124,1,106,1,107,2,111,76,124,0,106,2,124,1, - 106,2,107,2,111,76,124,0,106,3,124,1,106,3,107,2, - 111,76,124,2,124,1,106,0,107,2,111,76,124,0,106,4, - 124,1,106,4,107,2,111,76,124,0,106,5,124,1,106,5, - 107,2,83,0,4,0,116,6,107,10,114,96,1,0,1,0, - 1,0,100,1,83,0,88,0,100,0,83,0,41,2,78,70, - 41,7,114,106,0,0,0,114,15,0,0,0,114,93,0,0, - 0,114,103,0,0,0,218,6,99,97,99,104,101,100,218,12, - 104,97,115,95,108,111,99,97,116,105,111,110,114,90,0,0, - 0,41,3,114,26,0,0,0,90,5,111,116,104,101,114,90, - 4,115,109,115,108,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,6,95,95,101,113,95,95,135,1,0,0, - 115,20,0,0,0,0,1,6,1,2,1,12,1,12,1,12, - 1,10,1,12,1,12,1,14,1,122,17,77,111,100,117,108, - 101,83,112,101,99,46,95,95,101,113,95,95,99,1,0,0, - 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, - 0,115,58,0,0,0,124,0,106,0,100,0,107,8,114,52, - 124,0,106,1,100,0,107,9,114,52,124,0,106,2,114,52, - 116,3,100,0,107,8,114,38,116,4,130,1,116,3,160,5, - 124,0,106,1,161,1,124,0,95,0,124,0,106,0,83,0, - 41,1,78,41,6,114,108,0,0,0,114,103,0,0,0,114, - 107,0,0,0,218,19,95,98,111,111,116,115,116,114,97,112, - 95,101,120,116,101,114,110,97,108,218,19,78,111,116,73,109, - 112,108,101,109,101,110,116,101,100,69,114,114,111,114,90,11, - 95,103,101,116,95,99,97,99,104,101,100,41,1,114,26,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,112,0,0,0,147,1,0,0,115,12,0,0,0,0, - 2,10,1,16,1,8,1,4,1,14,1,122,17,77,111,100, - 117,108,101,83,112,101,99,46,99,97,99,104,101,100,99,2, - 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, - 0,0,0,115,10,0,0,0,124,1,124,0,95,0,100,0, - 83,0,41,1,78,41,1,114,108,0,0,0,41,2,114,26, - 0,0,0,114,112,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,112,0,0,0,156,1,0,0, - 115,2,0,0,0,0,2,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,36,0,0, - 0,124,0,106,0,100,1,107,8,114,26,124,0,106,1,160, - 2,100,2,161,1,100,3,25,0,83,0,124,0,106,1,83, - 0,100,1,83,0,41,4,122,32,84,104,101,32,110,97,109, - 101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,39, - 115,32,112,97,114,101,110,116,46,78,218,1,46,114,19,0, - 0,0,41,3,114,106,0,0,0,114,15,0,0,0,218,10, - 114,112,97,114,116,105,116,105,111,110,41,1,114,26,0,0, + 97,116,105,111,110,115,96,44,32,116,104,101,32,105,109,112, + 111,114,116,10,32,32,32,32,115,121,115,116,101,109,32,119, + 105,108,108,32,99,111,110,115,105,100,101,114,32,109,111,100, + 117,108,101,115,32,108,111,97,100,101,100,32,102,114,111,109, + 32,116,104,101,32,115,112,101,99,32,97,115,32,112,97,99, + 107,97,103,101,115,46,10,10,32,32,32,32,79,110,108,121, + 32,102,105,110,100,101,114,115,32,40,115,101,101,32,105,109, + 112,111,114,116,108,105,98,46,97,98,99,46,77,101,116,97, + 80,97,116,104,70,105,110,100,101,114,32,97,110,100,10,32, + 32,32,32,105,109,112,111,114,116,108,105,98,46,97,98,99, + 46,80,97,116,104,69,110,116,114,121,70,105,110,100,101,114, + 41,32,115,104,111,117,108,100,32,109,111,100,105,102,121,32, + 77,111,100,117,108,101,83,112,101,99,32,105,110,115,116,97, + 110,99,101,115,46,10,10,32,32,32,32,78,41,3,218,6, + 111,114,105,103,105,110,218,12,108,111,97,100,101,114,95,115, + 116,97,116,101,218,10,105,115,95,112,97,99,107,97,103,101, + 99,3,0,0,0,3,0,0,0,6,0,0,0,2,0,0, + 0,67,0,0,0,115,54,0,0,0,124,1,124,0,95,0, + 124,2,124,0,95,1,124,3,124,0,95,2,124,4,124,0, + 95,3,124,5,114,32,103,0,110,2,100,0,124,0,95,4, + 100,1,124,0,95,5,100,0,124,0,95,6,100,0,83,0, + 41,2,78,70,41,7,114,15,0,0,0,114,93,0,0,0, + 114,103,0,0,0,114,104,0,0,0,218,26,115,117,98,109, + 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, + 97,116,105,111,110,115,218,13,95,115,101,116,95,102,105,108, + 101,97,116,116,114,218,7,95,99,97,99,104,101,100,41,6, + 114,26,0,0,0,114,15,0,0,0,114,93,0,0,0,114, + 103,0,0,0,114,104,0,0,0,114,105,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,27,0, + 0,0,113,1,0,0,115,14,0,0,0,0,2,6,1,6, + 1,6,1,6,1,14,3,6,1,122,19,77,111,100,117,108, + 101,83,112,101,99,46,95,95,105,110,105,116,95,95,99,1, + 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, + 0,0,0,115,102,0,0,0,100,1,160,0,124,0,106,1, + 161,1,100,2,160,0,124,0,106,2,161,1,103,2,125,1, + 124,0,106,3,100,0,107,9,114,52,124,1,160,4,100,3, + 160,0,124,0,106,3,161,1,161,1,1,0,124,0,106,5, + 100,0,107,9,114,80,124,1,160,4,100,4,160,0,124,0, + 106,5,161,1,161,1,1,0,100,5,160,0,124,0,106,6, + 106,7,100,6,160,8,124,1,161,1,161,2,83,0,41,7, + 78,122,9,110,97,109,101,61,123,33,114,125,122,11,108,111, + 97,100,101,114,61,123,33,114,125,122,11,111,114,105,103,105, + 110,61,123,33,114,125,122,29,115,117,98,109,111,100,117,108, + 101,95,115,101,97,114,99,104,95,108,111,99,97,116,105,111, + 110,115,61,123,125,122,6,123,125,40,123,125,41,122,2,44, + 32,41,9,114,38,0,0,0,114,15,0,0,0,114,93,0, + 0,0,114,103,0,0,0,218,6,97,112,112,101,110,100,114, + 106,0,0,0,218,9,95,95,99,108,97,115,115,95,95,114, + 1,0,0,0,218,4,106,111,105,110,41,2,114,26,0,0, + 0,114,47,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,40,0,0,0,125,1,0,0,115,16, + 0,0,0,0,1,10,1,14,1,10,1,18,1,10,1,8, + 1,10,1,122,19,77,111,100,117,108,101,83,112,101,99,46, + 95,95,114,101,112,114,95,95,99,2,0,0,0,0,0,0, + 0,3,0,0,0,11,0,0,0,67,0,0,0,115,102,0, + 0,0,124,0,106,0,125,2,121,70,124,0,106,1,124,1, + 106,1,107,2,111,76,124,0,106,2,124,1,106,2,107,2, + 111,76,124,0,106,3,124,1,106,3,107,2,111,76,124,2, + 124,1,106,0,107,2,111,76,124,0,106,4,124,1,106,4, + 107,2,111,76,124,0,106,5,124,1,106,5,107,2,83,0, + 4,0,116,6,107,10,114,96,1,0,1,0,1,0,100,1, + 83,0,88,0,100,0,83,0,41,2,78,70,41,7,114,106, + 0,0,0,114,15,0,0,0,114,93,0,0,0,114,103,0, + 0,0,218,6,99,97,99,104,101,100,218,12,104,97,115,95, + 108,111,99,97,116,105,111,110,114,90,0,0,0,41,3,114, + 26,0,0,0,90,5,111,116,104,101,114,90,4,115,109,115, + 108,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,6,95,95,101,113,95,95,135,1,0,0,115,20,0,0, + 0,0,1,6,1,2,1,12,1,12,1,12,1,10,1,12, + 1,12,1,14,1,122,17,77,111,100,117,108,101,83,112,101, + 99,46,95,95,101,113,95,95,99,1,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,67,0,0,0,115,58,0, + 0,0,124,0,106,0,100,0,107,8,114,52,124,0,106,1, + 100,0,107,9,114,52,124,0,106,2,114,52,116,3,100,0, + 107,8,114,38,116,4,130,1,116,3,160,5,124,0,106,1, + 161,1,124,0,95,0,124,0,106,0,83,0,41,1,78,41, + 6,114,108,0,0,0,114,103,0,0,0,114,107,0,0,0, + 218,19,95,98,111,111,116,115,116,114,97,112,95,101,120,116, + 101,114,110,97,108,218,19,78,111,116,73,109,112,108,101,109, + 101,110,116,101,100,69,114,114,111,114,90,11,95,103,101,116, + 95,99,97,99,104,101,100,41,1,114,26,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,112,0, + 0,0,147,1,0,0,115,12,0,0,0,0,2,10,1,16, + 1,8,1,4,1,14,1,122,17,77,111,100,117,108,101,83, + 112,101,99,46,99,97,99,104,101,100,99,2,0,0,0,0, + 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, + 10,0,0,0,124,1,124,0,95,0,100,0,83,0,41,1, + 78,41,1,114,108,0,0,0,41,2,114,26,0,0,0,114, + 112,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,112,0,0,0,156,1,0,0,115,2,0,0, + 0,0,2,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,36,0,0,0,124,0,106, + 0,100,1,107,8,114,26,124,0,106,1,160,2,100,2,161, + 1,100,3,25,0,83,0,124,0,106,1,83,0,100,1,83, + 0,41,4,122,32,84,104,101,32,110,97,109,101,32,111,102, + 32,116,104,101,32,109,111,100,117,108,101,39,115,32,112,97, + 114,101,110,116,46,78,218,1,46,114,19,0,0,0,41,3, + 114,106,0,0,0,114,15,0,0,0,218,10,114,112,97,114, + 116,105,116,105,111,110,41,1,114,26,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,6,112,97, + 114,101,110,116,160,1,0,0,115,6,0,0,0,0,3,10, + 1,16,2,122,17,77,111,100,117,108,101,83,112,101,99,46, + 112,97,114,101,110,116,99,1,0,0,0,0,0,0,0,1, + 0,0,0,1,0,0,0,67,0,0,0,115,6,0,0,0, + 124,0,106,0,83,0,41,1,78,41,1,114,107,0,0,0, + 41,1,114,26,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,113,0,0,0,168,1,0,0,115, + 2,0,0,0,0,2,122,23,77,111,100,117,108,101,83,112, + 101,99,46,104,97,115,95,108,111,99,97,116,105,111,110,99, + 2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, + 67,0,0,0,115,14,0,0,0,116,0,124,1,131,1,124, + 0,95,1,100,0,83,0,41,1,78,41,2,218,4,98,111, + 111,108,114,107,0,0,0,41,2,114,26,0,0,0,218,5, + 118,97,108,117,101,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,113,0,0,0,172,1,0,0,115,2,0, + 0,0,0,2,41,12,114,1,0,0,0,114,0,0,0,0, + 114,2,0,0,0,114,3,0,0,0,114,27,0,0,0,114, + 40,0,0,0,114,114,0,0,0,218,8,112,114,111,112,101, + 114,116,121,114,112,0,0,0,218,6,115,101,116,116,101,114, + 114,119,0,0,0,114,113,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,102, + 0,0,0,76,1,0,0,115,18,0,0,0,12,37,4,1, + 14,11,8,10,8,12,12,9,14,4,12,8,12,4,114,102, + 0,0,0,41,2,114,103,0,0,0,114,105,0,0,0,99, + 2,0,0,0,2,0,0,0,6,0,0,0,14,0,0,0, + 67,0,0,0,115,154,0,0,0,116,0,124,1,100,1,131, + 2,114,74,116,1,100,2,107,8,114,22,116,2,130,1,116, + 1,106,3,125,4,124,3,100,2,107,8,114,48,124,4,124, + 0,124,1,100,3,141,2,83,0,124,3,114,56,103,0,110, + 2,100,2,125,5,124,4,124,0,124,1,124,5,100,4,141, + 3,83,0,124,3,100,2,107,8,114,138,116,0,124,1,100, + 5,131,2,114,134,121,14,124,1,160,4,124,0,161,1,125, + 3,87,0,113,138,4,0,116,5,107,10,114,130,1,0,1, + 0,1,0,100,2,125,3,89,0,113,138,88,0,110,4,100, + 6,125,3,116,6,124,0,124,1,124,2,124,3,100,7,141, + 4,83,0,41,8,122,53,82,101,116,117,114,110,32,97,32, + 109,111,100,117,108,101,32,115,112,101,99,32,98,97,115,101, + 100,32,111,110,32,118,97,114,105,111,117,115,32,108,111,97, + 100,101,114,32,109,101,116,104,111,100,115,46,90,12,103,101, + 116,95,102,105,108,101,110,97,109,101,78,41,1,114,93,0, + 0,0,41,2,114,93,0,0,0,114,106,0,0,0,114,105, + 0,0,0,70,41,2,114,103,0,0,0,114,105,0,0,0, + 41,7,114,4,0,0,0,114,115,0,0,0,114,116,0,0, + 0,218,23,115,112,101,99,95,102,114,111,109,95,102,105,108, + 101,95,108,111,99,97,116,105,111,110,114,105,0,0,0,114, + 70,0,0,0,114,102,0,0,0,41,6,114,15,0,0,0, + 114,93,0,0,0,114,103,0,0,0,114,105,0,0,0,114, + 124,0,0,0,90,6,115,101,97,114,99,104,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,78,0,0,0, + 177,1,0,0,115,34,0,0,0,0,2,10,1,8,1,4, + 1,6,2,8,1,12,1,12,1,6,1,8,2,8,1,10, + 1,2,1,14,1,14,1,12,3,4,2,114,78,0,0,0, + 99,3,0,0,0,0,0,0,0,8,0,0,0,53,0,0, + 0,67,0,0,0,115,56,1,0,0,121,10,124,0,106,0, + 125,3,87,0,110,20,4,0,116,1,107,10,114,30,1,0, + 1,0,1,0,89,0,110,14,88,0,124,3,100,0,107,9, + 114,44,124,3,83,0,124,0,106,2,125,4,124,1,100,0, + 107,8,114,90,121,10,124,0,106,3,125,1,87,0,110,20, + 4,0,116,1,107,10,114,88,1,0,1,0,1,0,89,0, + 110,2,88,0,121,10,124,0,106,4,125,5,87,0,110,24, + 4,0,116,1,107,10,114,124,1,0,1,0,1,0,100,0, + 125,5,89,0,110,2,88,0,124,2,100,0,107,8,114,184, + 124,5,100,0,107,8,114,180,121,10,124,1,106,5,125,2, + 87,0,113,184,4,0,116,1,107,10,114,176,1,0,1,0, + 1,0,100,0,125,2,89,0,113,184,88,0,110,4,124,5, + 125,2,121,10,124,0,106,6,125,6,87,0,110,24,4,0, + 116,1,107,10,114,218,1,0,1,0,1,0,100,0,125,6, + 89,0,110,2,88,0,121,14,116,7,124,0,106,8,131,1, + 125,7,87,0,110,26,4,0,116,1,107,10,144,1,114,4, + 1,0,1,0,1,0,100,0,125,7,89,0,110,2,88,0, + 116,9,124,4,124,1,124,2,100,1,141,3,125,3,124,5, + 100,0,107,8,144,1,114,34,100,2,110,2,100,3,124,3, + 95,10,124,6,124,3,95,11,124,7,124,3,95,12,124,3, + 83,0,41,4,78,41,1,114,103,0,0,0,70,84,41,13, + 114,89,0,0,0,114,90,0,0,0,114,1,0,0,0,114, + 85,0,0,0,114,92,0,0,0,90,7,95,79,82,73,71, + 73,78,218,10,95,95,99,97,99,104,101,100,95,95,218,4, + 108,105,115,116,218,8,95,95,112,97,116,104,95,95,114,102, + 0,0,0,114,107,0,0,0,114,112,0,0,0,114,106,0, + 0,0,41,8,114,83,0,0,0,114,93,0,0,0,114,103, + 0,0,0,114,82,0,0,0,114,15,0,0,0,90,8,108, + 111,99,97,116,105,111,110,114,112,0,0,0,114,106,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,6,112,97,114,101,110,116,160,1,0,0,115,6,0,0, - 0,0,3,10,1,16,2,122,17,77,111,100,117,108,101,83, - 112,101,99,46,112,97,114,101,110,116,99,1,0,0,0,0, - 0,0,0,1,0,0,0,1,0,0,0,67,0,0,0,115, - 6,0,0,0,124,0,106,0,83,0,41,1,78,41,1,114, - 107,0,0,0,41,1,114,26,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,113,0,0,0,168, - 1,0,0,115,2,0,0,0,0,2,122,23,77,111,100,117, - 108,101,83,112,101,99,46,104,97,115,95,108,111,99,97,116, - 105,111,110,99,2,0,0,0,0,0,0,0,2,0,0,0, - 2,0,0,0,67,0,0,0,115,14,0,0,0,116,0,124, - 1,131,1,124,0,95,1,100,0,83,0,41,1,78,41,2, - 218,4,98,111,111,108,114,107,0,0,0,41,2,114,26,0, - 0,0,218,5,118,97,108,117,101,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,113,0,0,0,172,1,0, - 0,115,2,0,0,0,0,2,41,12,114,1,0,0,0,114, - 0,0,0,0,114,2,0,0,0,114,3,0,0,0,114,27, - 0,0,0,114,40,0,0,0,114,114,0,0,0,218,8,112, - 114,111,112,101,114,116,121,114,112,0,0,0,218,6,115,101, - 116,116,101,114,114,119,0,0,0,114,113,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,102,0,0,0,76,1,0,0,115,18,0,0,0, - 12,37,4,1,14,11,8,10,8,12,12,9,14,4,12,8, - 12,4,114,102,0,0,0,41,2,114,103,0,0,0,114,105, - 0,0,0,99,2,0,0,0,2,0,0,0,6,0,0,0, - 14,0,0,0,67,0,0,0,115,154,0,0,0,116,0,124, - 1,100,1,131,2,114,74,116,1,100,2,107,8,114,22,116, - 2,130,1,116,1,106,3,125,4,124,3,100,2,107,8,114, - 48,124,4,124,0,124,1,100,3,141,2,83,0,124,3,114, - 56,103,0,110,2,100,2,125,5,124,4,124,0,124,1,124, - 5,100,4,141,3,83,0,124,3,100,2,107,8,114,138,116, - 0,124,1,100,5,131,2,114,134,121,14,124,1,160,4,124, - 0,161,1,125,3,87,0,113,138,4,0,116,5,107,10,114, - 130,1,0,1,0,1,0,100,2,125,3,89,0,113,138,88, - 0,110,4,100,6,125,3,116,6,124,0,124,1,124,2,124, - 3,100,7,141,4,83,0,41,8,122,53,82,101,116,117,114, - 110,32,97,32,109,111,100,117,108,101,32,115,112,101,99,32, - 98,97,115,101,100,32,111,110,32,118,97,114,105,111,117,115, - 32,108,111,97,100,101,114,32,109,101,116,104,111,100,115,46, - 90,12,103,101,116,95,102,105,108,101,110,97,109,101,78,41, - 1,114,93,0,0,0,41,2,114,93,0,0,0,114,106,0, - 0,0,114,105,0,0,0,70,41,2,114,103,0,0,0,114, - 105,0,0,0,41,7,114,4,0,0,0,114,115,0,0,0, - 114,116,0,0,0,218,23,115,112,101,99,95,102,114,111,109, - 95,102,105,108,101,95,108,111,99,97,116,105,111,110,114,105, - 0,0,0,114,70,0,0,0,114,102,0,0,0,41,6,114, - 15,0,0,0,114,93,0,0,0,114,103,0,0,0,114,105, - 0,0,0,114,124,0,0,0,90,6,115,101,97,114,99,104, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 78,0,0,0,177,1,0,0,115,34,0,0,0,0,2,10, - 1,8,1,4,1,6,2,8,1,12,1,12,1,6,1,8, - 2,8,1,10,1,2,1,14,1,14,1,12,3,4,2,114, - 78,0,0,0,99,3,0,0,0,0,0,0,0,8,0,0, - 0,53,0,0,0,67,0,0,0,115,56,1,0,0,121,10, - 124,0,106,0,125,3,87,0,110,20,4,0,116,1,107,10, - 114,30,1,0,1,0,1,0,89,0,110,14,88,0,124,3, - 100,0,107,9,114,44,124,3,83,0,124,0,106,2,125,4, - 124,1,100,0,107,8,114,90,121,10,124,0,106,3,125,1, - 87,0,110,20,4,0,116,1,107,10,114,88,1,0,1,0, - 1,0,89,0,110,2,88,0,121,10,124,0,106,4,125,5, - 87,0,110,24,4,0,116,1,107,10,114,124,1,0,1,0, - 1,0,100,0,125,5,89,0,110,2,88,0,124,2,100,0, - 107,8,114,184,124,5,100,0,107,8,114,180,121,10,124,1, - 106,5,125,2,87,0,113,184,4,0,116,1,107,10,114,176, - 1,0,1,0,1,0,100,0,125,2,89,0,113,184,88,0, - 110,4,124,5,125,2,121,10,124,0,106,6,125,6,87,0, - 110,24,4,0,116,1,107,10,114,218,1,0,1,0,1,0, - 100,0,125,6,89,0,110,2,88,0,121,14,116,7,124,0, - 106,8,131,1,125,7,87,0,110,26,4,0,116,1,107,10, - 144,1,114,4,1,0,1,0,1,0,100,0,125,7,89,0, - 110,2,88,0,116,9,124,4,124,1,124,2,100,1,141,3, - 125,3,124,5,100,0,107,8,144,1,114,34,100,2,110,2, - 100,3,124,3,95,10,124,6,124,3,95,11,124,7,124,3, - 95,12,124,3,83,0,41,4,78,41,1,114,103,0,0,0, - 70,84,41,13,114,89,0,0,0,114,90,0,0,0,114,1, - 0,0,0,114,85,0,0,0,114,92,0,0,0,90,7,95, - 79,82,73,71,73,78,218,10,95,95,99,97,99,104,101,100, - 95,95,218,4,108,105,115,116,218,8,95,95,112,97,116,104, - 95,95,114,102,0,0,0,114,107,0,0,0,114,112,0,0, - 0,114,106,0,0,0,41,8,114,83,0,0,0,114,93,0, - 0,0,114,103,0,0,0,114,82,0,0,0,114,15,0,0, - 0,90,8,108,111,99,97,116,105,111,110,114,112,0,0,0, - 114,106,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,17,95,115,112,101,99,95,102,114,111,109, - 95,109,111,100,117,108,101,203,1,0,0,115,72,0,0,0, - 0,2,2,1,10,1,14,1,6,2,8,1,4,2,6,1, - 8,1,2,1,10,1,14,2,6,1,2,1,10,1,14,1, - 10,1,8,1,8,1,2,1,10,1,14,1,12,2,4,1, - 2,1,10,1,14,1,10,1,2,1,14,1,16,1,10,2, - 14,1,20,1,6,1,6,1,114,128,0,0,0,70,41,1, - 218,8,111,118,101,114,114,105,100,101,99,2,0,0,0,1, - 0,0,0,5,0,0,0,59,0,0,0,67,0,0,0,115, - 212,1,0,0,124,2,115,20,116,0,124,1,100,1,100,0, - 131,3,100,0,107,8,114,54,121,12,124,0,106,1,124,1, - 95,2,87,0,110,20,4,0,116,3,107,10,114,52,1,0, - 1,0,1,0,89,0,110,2,88,0,124,2,115,74,116,0, - 124,1,100,2,100,0,131,3,100,0,107,8,114,166,124,0, - 106,4,125,3,124,3,100,0,107,8,114,134,124,0,106,5, - 100,0,107,9,114,134,116,6,100,0,107,8,114,110,116,7, - 130,1,116,6,106,8,125,4,124,4,160,9,124,4,161,1, - 125,3,124,0,106,5,124,3,95,10,121,10,124,3,124,1, - 95,11,87,0,110,20,4,0,116,3,107,10,114,164,1,0, - 1,0,1,0,89,0,110,2,88,0,124,2,115,186,116,0, - 124,1,100,3,100,0,131,3,100,0,107,8,114,220,121,12, - 124,0,106,12,124,1,95,13,87,0,110,20,4,0,116,3, - 107,10,114,218,1,0,1,0,1,0,89,0,110,2,88,0, - 121,10,124,0,124,1,95,14,87,0,110,20,4,0,116,3, - 107,10,114,250,1,0,1,0,1,0,89,0,110,2,88,0, - 124,2,144,1,115,20,116,0,124,1,100,4,100,0,131,3, - 100,0,107,8,144,1,114,68,124,0,106,5,100,0,107,9, - 144,1,114,68,121,12,124,0,106,5,124,1,95,15,87,0, - 110,22,4,0,116,3,107,10,144,1,114,66,1,0,1,0, - 1,0,89,0,110,2,88,0,124,0,106,16,144,1,114,208, - 124,2,144,1,115,100,116,0,124,1,100,5,100,0,131,3, - 100,0,107,8,144,1,114,136,121,12,124,0,106,17,124,1, - 95,18,87,0,110,22,4,0,116,3,107,10,144,1,114,134, + 218,17,95,115,112,101,99,95,102,114,111,109,95,109,111,100, + 117,108,101,203,1,0,0,115,72,0,0,0,0,2,2,1, + 10,1,14,1,6,2,8,1,4,2,6,1,8,1,2,1, + 10,1,14,2,6,1,2,1,10,1,14,1,10,1,8,1, + 8,1,2,1,10,1,14,1,12,2,4,1,2,1,10,1, + 14,1,10,1,2,1,14,1,16,1,10,2,14,1,20,1, + 6,1,6,1,114,128,0,0,0,70,41,1,218,8,111,118, + 101,114,114,105,100,101,99,2,0,0,0,1,0,0,0,5, + 0,0,0,59,0,0,0,67,0,0,0,115,212,1,0,0, + 124,2,115,20,116,0,124,1,100,1,100,0,131,3,100,0, + 107,8,114,54,121,12,124,0,106,1,124,1,95,2,87,0, + 110,20,4,0,116,3,107,10,114,52,1,0,1,0,1,0, + 89,0,110,2,88,0,124,2,115,74,116,0,124,1,100,2, + 100,0,131,3,100,0,107,8,114,166,124,0,106,4,125,3, + 124,3,100,0,107,8,114,134,124,0,106,5,100,0,107,9, + 114,134,116,6,100,0,107,8,114,110,116,7,130,1,116,6, + 106,8,125,4,124,4,160,9,124,4,161,1,125,3,124,0, + 106,5,124,3,95,10,121,10,124,3,124,1,95,11,87,0, + 110,20,4,0,116,3,107,10,114,164,1,0,1,0,1,0, + 89,0,110,2,88,0,124,2,115,186,116,0,124,1,100,3, + 100,0,131,3,100,0,107,8,114,220,121,12,124,0,106,12, + 124,1,95,13,87,0,110,20,4,0,116,3,107,10,114,218, + 1,0,1,0,1,0,89,0,110,2,88,0,121,10,124,0, + 124,1,95,14,87,0,110,20,4,0,116,3,107,10,114,250, 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, - 115,160,116,0,124,1,100,6,100,0,131,3,100,0,107,8, - 144,1,114,208,124,0,106,19,100,0,107,9,144,1,114,208, - 121,12,124,0,106,19,124,1,95,20,87,0,110,22,4,0, - 116,3,107,10,144,1,114,206,1,0,1,0,1,0,89,0, - 110,2,88,0,124,1,83,0,41,7,78,114,1,0,0,0, - 114,85,0,0,0,218,11,95,95,112,97,99,107,97,103,101, - 95,95,114,127,0,0,0,114,92,0,0,0,114,125,0,0, - 0,41,21,114,6,0,0,0,114,15,0,0,0,114,1,0, - 0,0,114,90,0,0,0,114,93,0,0,0,114,106,0,0, - 0,114,115,0,0,0,114,116,0,0,0,218,16,95,78,97, - 109,101,115,112,97,99,101,76,111,97,100,101,114,218,7,95, - 95,110,101,119,95,95,90,5,95,112,97,116,104,114,85,0, - 0,0,114,119,0,0,0,114,130,0,0,0,114,89,0,0, - 0,114,127,0,0,0,114,113,0,0,0,114,103,0,0,0, - 114,92,0,0,0,114,112,0,0,0,114,125,0,0,0,41, - 5,114,82,0,0,0,114,83,0,0,0,114,129,0,0,0, - 114,93,0,0,0,114,131,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,18,95,105,110,105,116, - 95,109,111,100,117,108,101,95,97,116,116,114,115,248,1,0, - 0,115,92,0,0,0,0,4,20,1,2,1,12,1,14,1, - 6,2,20,1,6,1,8,2,10,1,8,1,4,1,6,2, - 10,1,8,1,2,1,10,1,14,1,6,2,20,1,2,1, - 12,1,14,1,6,2,2,1,10,1,14,1,6,2,24,1, - 12,1,2,1,12,1,16,1,6,2,8,1,24,1,2,1, - 12,1,16,1,6,2,24,1,12,1,2,1,12,1,16,1, - 6,1,114,133,0,0,0,99,1,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,115,82,0,0, - 0,100,1,125,1,116,0,124,0,106,1,100,2,131,2,114, - 30,124,0,106,1,160,2,124,0,161,1,125,1,110,20,116, - 0,124,0,106,1,100,3,131,2,114,50,116,3,100,4,131, - 1,130,1,124,1,100,1,107,8,114,68,116,4,124,0,106, - 5,131,1,125,1,116,6,124,0,124,1,131,2,1,0,124, - 1,83,0,41,5,122,43,67,114,101,97,116,101,32,97,32, - 109,111,100,117,108,101,32,98,97,115,101,100,32,111,110,32, - 116,104,101,32,112,114,111,118,105,100,101,100,32,115,112,101, - 99,46,78,218,13,99,114,101,97,116,101,95,109,111,100,117, - 108,101,218,11,101,120,101,99,95,109,111,100,117,108,101,122, - 66,108,111,97,100,101,114,115,32,116,104,97,116,32,100,101, - 102,105,110,101,32,101,120,101,99,95,109,111,100,117,108,101, - 40,41,32,109,117,115,116,32,97,108,115,111,32,100,101,102, - 105,110,101,32,99,114,101,97,116,101,95,109,111,100,117,108, - 101,40,41,41,7,114,4,0,0,0,114,93,0,0,0,114, - 134,0,0,0,114,70,0,0,0,114,16,0,0,0,114,15, - 0,0,0,114,133,0,0,0,41,2,114,82,0,0,0,114, + 115,20,116,0,124,1,100,4,100,0,131,3,100,0,107,8, + 144,1,114,68,124,0,106,5,100,0,107,9,144,1,114,68, + 121,12,124,0,106,5,124,1,95,15,87,0,110,22,4,0, + 116,3,107,10,144,1,114,66,1,0,1,0,1,0,89,0, + 110,2,88,0,124,0,106,16,144,1,114,208,124,2,144,1, + 115,100,116,0,124,1,100,5,100,0,131,3,100,0,107,8, + 144,1,114,136,121,12,124,0,106,17,124,1,95,18,87,0, + 110,22,4,0,116,3,107,10,144,1,114,134,1,0,1,0, + 1,0,89,0,110,2,88,0,124,2,144,1,115,160,116,0, + 124,1,100,6,100,0,131,3,100,0,107,8,144,1,114,208, + 124,0,106,19,100,0,107,9,144,1,114,208,121,12,124,0, + 106,19,124,1,95,20,87,0,110,22,4,0,116,3,107,10, + 144,1,114,206,1,0,1,0,1,0,89,0,110,2,88,0, + 124,1,83,0,41,7,78,114,1,0,0,0,114,85,0,0, + 0,218,11,95,95,112,97,99,107,97,103,101,95,95,114,127, + 0,0,0,114,92,0,0,0,114,125,0,0,0,41,21,114, + 6,0,0,0,114,15,0,0,0,114,1,0,0,0,114,90, + 0,0,0,114,93,0,0,0,114,106,0,0,0,114,115,0, + 0,0,114,116,0,0,0,218,16,95,78,97,109,101,115,112, + 97,99,101,76,111,97,100,101,114,218,7,95,95,110,101,119, + 95,95,90,5,95,112,97,116,104,114,85,0,0,0,114,119, + 0,0,0,114,130,0,0,0,114,89,0,0,0,114,127,0, + 0,0,114,113,0,0,0,114,103,0,0,0,114,92,0,0, + 0,114,112,0,0,0,114,125,0,0,0,41,5,114,82,0, + 0,0,114,83,0,0,0,114,129,0,0,0,114,93,0,0, + 0,114,131,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,18,95,105,110,105,116,95,109,111,100, + 117,108,101,95,97,116,116,114,115,248,1,0,0,115,92,0, + 0,0,0,4,20,1,2,1,12,1,14,1,6,2,20,1, + 6,1,8,2,10,1,8,1,4,1,6,2,10,1,8,1, + 2,1,10,1,14,1,6,2,20,1,2,1,12,1,14,1, + 6,2,2,1,10,1,14,1,6,2,24,1,12,1,2,1, + 12,1,16,1,6,2,8,1,24,1,2,1,12,1,16,1, + 6,2,24,1,12,1,2,1,12,1,16,1,6,1,114,133, + 0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,67,0,0,0,115,82,0,0,0,100,1,125, + 1,116,0,124,0,106,1,100,2,131,2,114,30,124,0,106, + 1,160,2,124,0,161,1,125,1,110,20,116,0,124,0,106, + 1,100,3,131,2,114,50,116,3,100,4,131,1,130,1,124, + 1,100,1,107,8,114,68,116,4,124,0,106,5,131,1,125, + 1,116,6,124,0,124,1,131,2,1,0,124,1,83,0,41, + 5,122,43,67,114,101,97,116,101,32,97,32,109,111,100,117, + 108,101,32,98,97,115,101,100,32,111,110,32,116,104,101,32, + 112,114,111,118,105,100,101,100,32,115,112,101,99,46,78,218, + 13,99,114,101,97,116,101,95,109,111,100,117,108,101,218,11, + 101,120,101,99,95,109,111,100,117,108,101,122,66,108,111,97, + 100,101,114,115,32,116,104,97,116,32,100,101,102,105,110,101, + 32,101,120,101,99,95,109,111,100,117,108,101,40,41,32,109, + 117,115,116,32,97,108,115,111,32,100,101,102,105,110,101,32, + 99,114,101,97,116,101,95,109,111,100,117,108,101,40,41,41, + 7,114,4,0,0,0,114,93,0,0,0,114,134,0,0,0, + 114,70,0,0,0,114,16,0,0,0,114,15,0,0,0,114, + 133,0,0,0,41,2,114,82,0,0,0,114,83,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, + 16,109,111,100,117,108,101,95,102,114,111,109,95,115,112,101, + 99,52,2,0,0,115,18,0,0,0,0,3,4,1,12,3, + 14,1,12,1,8,2,8,1,10,1,10,1,114,136,0,0, + 0,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,67,0,0,0,115,106,0,0,0,124,0,106,0,100, + 1,107,8,114,14,100,2,110,4,124,0,106,0,125,1,124, + 0,106,1,100,1,107,8,114,66,124,0,106,2,100,1,107, + 8,114,50,100,3,160,3,124,1,161,1,83,0,100,4,160, + 3,124,1,124,0,106,2,161,2,83,0,110,36,124,0,106, + 4,114,86,100,5,160,3,124,1,124,0,106,1,161,2,83, + 0,100,6,160,3,124,0,106,0,124,0,106,1,161,2,83, + 0,100,1,83,0,41,7,122,38,82,101,116,117,114,110,32, + 116,104,101,32,114,101,112,114,32,116,111,32,117,115,101,32, + 102,111,114,32,116,104,101,32,109,111,100,117,108,101,46,78, + 114,87,0,0,0,122,13,60,109,111,100,117,108,101,32,123, + 33,114,125,62,122,20,60,109,111,100,117,108,101,32,123,33, + 114,125,32,40,123,33,114,125,41,62,122,23,60,109,111,100, + 117,108,101,32,123,33,114,125,32,102,114,111,109,32,123,33, + 114,125,62,122,18,60,109,111,100,117,108,101,32,123,33,114, + 125,32,40,123,125,41,62,41,5,114,15,0,0,0,114,103, + 0,0,0,114,93,0,0,0,114,38,0,0,0,114,113,0, + 0,0,41,2,114,82,0,0,0,114,15,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,91,0, + 0,0,69,2,0,0,115,16,0,0,0,0,3,20,1,10, + 1,10,1,10,2,16,2,6,1,14,2,114,91,0,0,0, + 99,2,0,0,0,0,0,0,0,4,0,0,0,12,0,0, + 0,67,0,0,0,115,178,0,0,0,124,0,106,0,125,2, + 116,1,124,2,131,1,143,148,1,0,116,2,106,3,160,4, + 124,2,161,1,124,1,107,9,114,54,100,1,160,5,124,2, + 161,1,125,3,116,6,124,3,124,2,100,2,141,2,130,1, + 124,0,106,7,100,3,107,8,114,106,124,0,106,8,100,3, + 107,8,114,88,116,6,100,4,124,0,106,0,100,2,141,2, + 130,1,116,9,124,0,124,1,100,5,100,6,141,3,1,0, + 124,1,83,0,116,9,124,0,124,1,100,5,100,6,141,3, + 1,0,116,10,124,0,106,7,100,7,131,2,115,146,124,0, + 106,7,160,11,124,2,161,1,1,0,110,12,124,0,106,7, + 160,12,124,1,161,1,1,0,87,0,100,3,81,0,82,0, + 88,0,116,2,106,3,124,2,25,0,83,0,41,8,122,70, + 69,120,101,99,117,116,101,32,116,104,101,32,115,112,101,99, + 39,115,32,115,112,101,99,105,102,105,101,100,32,109,111,100, + 117,108,101,32,105,110,32,97,110,32,101,120,105,115,116,105, + 110,103,32,109,111,100,117,108,101,39,115,32,110,97,109,101, + 115,112,97,99,101,46,122,30,109,111,100,117,108,101,32,123, + 33,114,125,32,110,111,116,32,105,110,32,115,121,115,46,109, + 111,100,117,108,101,115,41,1,114,15,0,0,0,78,122,14, + 109,105,115,115,105,110,103,32,108,111,97,100,101,114,84,41, + 1,114,129,0,0,0,114,135,0,0,0,41,13,114,15,0, + 0,0,114,42,0,0,0,114,14,0,0,0,114,79,0,0, + 0,114,30,0,0,0,114,38,0,0,0,114,70,0,0,0, + 114,93,0,0,0,114,106,0,0,0,114,133,0,0,0,114, + 4,0,0,0,218,11,108,111,97,100,95,109,111,100,117,108, + 101,114,135,0,0,0,41,4,114,82,0,0,0,114,83,0, + 0,0,114,15,0,0,0,218,3,109,115,103,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,80,0,0,0, + 86,2,0,0,115,30,0,0,0,0,2,6,1,10,1,16, + 1,10,1,12,1,10,1,10,1,14,2,14,1,4,1,14, + 1,12,4,14,2,22,1,114,80,0,0,0,99,1,0,0, + 0,0,0,0,0,2,0,0,0,27,0,0,0,67,0,0, + 0,115,206,0,0,0,124,0,106,0,160,1,124,0,106,2, + 161,1,1,0,116,3,106,4,124,0,106,2,25,0,125,1, + 116,5,124,1,100,1,100,0,131,3,100,0,107,8,114,76, + 121,12,124,0,106,0,124,1,95,6,87,0,110,20,4,0, + 116,7,107,10,114,74,1,0,1,0,1,0,89,0,110,2, + 88,0,116,5,124,1,100,2,100,0,131,3,100,0,107,8, + 114,154,121,40,124,1,106,8,124,1,95,9,116,10,124,1, + 100,3,131,2,115,130,124,0,106,2,160,11,100,4,161,1, + 100,5,25,0,124,1,95,9,87,0,110,20,4,0,116,7, + 107,10,114,152,1,0,1,0,1,0,89,0,110,2,88,0, + 116,5,124,1,100,6,100,0,131,3,100,0,107,8,114,202, + 121,10,124,0,124,1,95,12,87,0,110,20,4,0,116,7, + 107,10,114,200,1,0,1,0,1,0,89,0,110,2,88,0, + 124,1,83,0,41,7,78,114,85,0,0,0,114,130,0,0, + 0,114,127,0,0,0,114,117,0,0,0,114,19,0,0,0, + 114,89,0,0,0,41,13,114,93,0,0,0,114,137,0,0, + 0,114,15,0,0,0,114,14,0,0,0,114,79,0,0,0, + 114,6,0,0,0,114,85,0,0,0,114,90,0,0,0,114, + 1,0,0,0,114,130,0,0,0,114,4,0,0,0,114,118, + 0,0,0,114,89,0,0,0,41,2,114,82,0,0,0,114, 83,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,218,16,109,111,100,117,108,101,95,102,114,111,109, - 95,115,112,101,99,52,2,0,0,115,18,0,0,0,0,3, - 4,1,12,3,14,1,12,1,8,2,8,1,10,1,10,1, - 114,136,0,0,0,99,1,0,0,0,0,0,0,0,2,0, - 0,0,4,0,0,0,67,0,0,0,115,106,0,0,0,124, - 0,106,0,100,1,107,8,114,14,100,2,110,4,124,0,106, - 0,125,1,124,0,106,1,100,1,107,8,114,66,124,0,106, - 2,100,1,107,8,114,50,100,3,160,3,124,1,161,1,83, - 0,100,4,160,3,124,1,124,0,106,2,161,2,83,0,110, - 36,124,0,106,4,114,86,100,5,160,3,124,1,124,0,106, - 1,161,2,83,0,100,6,160,3,124,0,106,0,124,0,106, - 1,161,2,83,0,100,1,83,0,41,7,122,38,82,101,116, - 117,114,110,32,116,104,101,32,114,101,112,114,32,116,111,32, - 117,115,101,32,102,111,114,32,116,104,101,32,109,111,100,117, - 108,101,46,78,114,87,0,0,0,122,13,60,109,111,100,117, - 108,101,32,123,33,114,125,62,122,20,60,109,111,100,117,108, - 101,32,123,33,114,125,32,40,123,33,114,125,41,62,122,23, - 60,109,111,100,117,108,101,32,123,33,114,125,32,102,114,111, - 109,32,123,33,114,125,62,122,18,60,109,111,100,117,108,101, - 32,123,33,114,125,32,40,123,125,41,62,41,5,114,15,0, - 0,0,114,103,0,0,0,114,93,0,0,0,114,38,0,0, - 0,114,113,0,0,0,41,2,114,82,0,0,0,114,15,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,91,0,0,0,69,2,0,0,115,16,0,0,0,0, - 3,20,1,10,1,10,1,10,2,16,2,6,1,14,2,114, - 91,0,0,0,99,2,0,0,0,0,0,0,0,4,0,0, - 0,12,0,0,0,67,0,0,0,115,178,0,0,0,124,0, - 106,0,125,2,116,1,124,2,131,1,143,148,1,0,116,2, - 106,3,160,4,124,2,161,1,124,1,107,9,114,54,100,1, - 160,5,124,2,161,1,125,3,116,6,124,3,124,2,100,2, - 141,2,130,1,124,0,106,7,100,3,107,8,114,106,124,0, - 106,8,100,3,107,8,114,88,116,6,100,4,124,0,106,0, - 100,2,141,2,130,1,116,9,124,0,124,1,100,5,100,6, - 141,3,1,0,124,1,83,0,116,9,124,0,124,1,100,5, - 100,6,141,3,1,0,116,10,124,0,106,7,100,7,131,2, - 115,146,124,0,106,7,160,11,124,2,161,1,1,0,110,12, - 124,0,106,7,160,12,124,1,161,1,1,0,87,0,100,3, - 81,0,82,0,88,0,116,2,106,3,124,2,25,0,83,0, - 41,8,122,70,69,120,101,99,117,116,101,32,116,104,101,32, - 115,112,101,99,39,115,32,115,112,101,99,105,102,105,101,100, - 32,109,111,100,117,108,101,32,105,110,32,97,110,32,101,120, - 105,115,116,105,110,103,32,109,111,100,117,108,101,39,115,32, - 110,97,109,101,115,112,97,99,101,46,122,30,109,111,100,117, - 108,101,32,123,33,114,125,32,110,111,116,32,105,110,32,115, - 121,115,46,109,111,100,117,108,101,115,41,1,114,15,0,0, - 0,78,122,14,109,105,115,115,105,110,103,32,108,111,97,100, - 101,114,84,41,1,114,129,0,0,0,114,135,0,0,0,41, - 13,114,15,0,0,0,114,42,0,0,0,114,14,0,0,0, - 114,79,0,0,0,114,30,0,0,0,114,38,0,0,0,114, - 70,0,0,0,114,93,0,0,0,114,106,0,0,0,114,133, - 0,0,0,114,4,0,0,0,218,11,108,111,97,100,95,109, - 111,100,117,108,101,114,135,0,0,0,41,4,114,82,0,0, - 0,114,83,0,0,0,114,15,0,0,0,218,3,109,115,103, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 80,0,0,0,86,2,0,0,115,30,0,0,0,0,2,6, - 1,10,1,16,1,10,1,12,1,10,1,10,1,14,2,14, - 1,4,1,14,1,12,4,14,2,22,1,114,80,0,0,0, - 99,1,0,0,0,0,0,0,0,2,0,0,0,27,0,0, - 0,67,0,0,0,115,206,0,0,0,124,0,106,0,160,1, - 124,0,106,2,161,1,1,0,116,3,106,4,124,0,106,2, - 25,0,125,1,116,5,124,1,100,1,100,0,131,3,100,0, - 107,8,114,76,121,12,124,0,106,0,124,1,95,6,87,0, - 110,20,4,0,116,7,107,10,114,74,1,0,1,0,1,0, - 89,0,110,2,88,0,116,5,124,1,100,2,100,0,131,3, - 100,0,107,8,114,154,121,40,124,1,106,8,124,1,95,9, - 116,10,124,1,100,3,131,2,115,130,124,0,106,2,160,11, - 100,4,161,1,100,5,25,0,124,1,95,9,87,0,110,20, - 4,0,116,7,107,10,114,152,1,0,1,0,1,0,89,0, - 110,2,88,0,116,5,124,1,100,6,100,0,131,3,100,0, - 107,8,114,202,121,10,124,0,124,1,95,12,87,0,110,20, - 4,0,116,7,107,10,114,200,1,0,1,0,1,0,89,0, - 110,2,88,0,124,1,83,0,41,7,78,114,85,0,0,0, - 114,130,0,0,0,114,127,0,0,0,114,117,0,0,0,114, - 19,0,0,0,114,89,0,0,0,41,13,114,93,0,0,0, - 114,137,0,0,0,114,15,0,0,0,114,14,0,0,0,114, - 79,0,0,0,114,6,0,0,0,114,85,0,0,0,114,90, - 0,0,0,114,1,0,0,0,114,130,0,0,0,114,4,0, - 0,0,114,118,0,0,0,114,89,0,0,0,41,2,114,82, + 0,0,0,218,25,95,108,111,97,100,95,98,97,99,107,119, + 97,114,100,95,99,111,109,112,97,116,105,98,108,101,110,2, + 0,0,115,40,0,0,0,0,4,14,2,12,1,16,1,2, + 1,12,1,14,1,6,1,16,1,2,4,8,1,10,1,22, + 1,14,1,6,1,16,1,2,1,10,1,14,1,6,1,114, + 139,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0, + 0,11,0,0,0,67,0,0,0,115,118,0,0,0,124,0, + 106,0,100,0,107,9,114,30,116,1,124,0,106,0,100,1, + 131,2,115,30,116,2,124,0,131,1,83,0,116,3,124,0, + 131,1,125,1,116,4,124,1,131,1,143,54,1,0,124,0, + 106,0,100,0,107,8,114,84,124,0,106,5,100,0,107,8, + 114,96,116,6,100,2,124,0,106,7,100,3,141,2,130,1, + 110,12,124,0,106,0,160,8,124,1,161,1,1,0,87,0, + 100,0,81,0,82,0,88,0,116,9,106,10,124,0,106,7, + 25,0,83,0,41,4,78,114,135,0,0,0,122,14,109,105, + 115,115,105,110,103,32,108,111,97,100,101,114,41,1,114,15, + 0,0,0,41,11,114,93,0,0,0,114,4,0,0,0,114, + 139,0,0,0,114,136,0,0,0,114,96,0,0,0,114,106, + 0,0,0,114,70,0,0,0,114,15,0,0,0,114,135,0, + 0,0,114,14,0,0,0,114,79,0,0,0,41,2,114,82, 0,0,0,114,83,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,25,95,108,111,97,100,95,98, - 97,99,107,119,97,114,100,95,99,111,109,112,97,116,105,98, - 108,101,110,2,0,0,115,40,0,0,0,0,4,14,2,12, - 1,16,1,2,1,12,1,14,1,6,1,16,1,2,4,8, - 1,10,1,22,1,14,1,6,1,16,1,2,1,10,1,14, - 1,6,1,114,139,0,0,0,99,1,0,0,0,0,0,0, - 0,2,0,0,0,11,0,0,0,67,0,0,0,115,118,0, - 0,0,124,0,106,0,100,0,107,9,114,30,116,1,124,0, - 106,0,100,1,131,2,115,30,116,2,124,0,131,1,83,0, - 116,3,124,0,131,1,125,1,116,4,124,1,131,1,143,54, - 1,0,124,0,106,0,100,0,107,8,114,84,124,0,106,5, - 100,0,107,8,114,96,116,6,100,2,124,0,106,7,100,3, - 141,2,130,1,110,12,124,0,106,0,160,8,124,1,161,1, - 1,0,87,0,100,0,81,0,82,0,88,0,116,9,106,10, - 124,0,106,7,25,0,83,0,41,4,78,114,135,0,0,0, - 122,14,109,105,115,115,105,110,103,32,108,111,97,100,101,114, - 41,1,114,15,0,0,0,41,11,114,93,0,0,0,114,4, - 0,0,0,114,139,0,0,0,114,136,0,0,0,114,96,0, - 0,0,114,106,0,0,0,114,70,0,0,0,114,15,0,0, - 0,114,135,0,0,0,114,14,0,0,0,114,79,0,0,0, - 41,2,114,82,0,0,0,114,83,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,218,14,95,108,111, - 97,100,95,117,110,108,111,99,107,101,100,139,2,0,0,115, - 20,0,0,0,0,2,10,2,12,1,8,2,8,1,10,1, - 10,1,10,1,16,3,22,5,114,140,0,0,0,99,1,0, - 0,0,0,0,0,0,1,0,0,0,9,0,0,0,67,0, - 0,0,115,30,0,0,0,116,0,124,0,106,1,131,1,143, - 10,1,0,116,2,124,0,131,1,83,0,81,0,82,0,88, - 0,100,1,83,0,41,2,122,191,82,101,116,117,114,110,32, - 97,32,110,101,119,32,109,111,100,117,108,101,32,111,98,106, - 101,99,116,44,32,108,111,97,100,101,100,32,98,121,32,116, - 104,101,32,115,112,101,99,39,115,32,108,111,97,100,101,114, - 46,10,10,32,32,32,32,84,104,101,32,109,111,100,117,108, - 101,32,105,115,32,110,111,116,32,97,100,100,101,100,32,116, - 111,32,105,116,115,32,112,97,114,101,110,116,46,10,10,32, - 32,32,32,73,102,32,97,32,109,111,100,117,108,101,32,105, - 115,32,97,108,114,101,97,100,121,32,105,110,32,115,121,115, - 46,109,111,100,117,108,101,115,44,32,116,104,97,116,32,101, - 120,105,115,116,105,110,103,32,109,111,100,117,108,101,32,103, - 101,116,115,10,32,32,32,32,99,108,111,98,98,101,114,101, - 100,46,10,10,32,32,32,32,78,41,3,114,42,0,0,0, - 114,15,0,0,0,114,140,0,0,0,41,1,114,82,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,81,0,0,0,162,2,0,0,115,4,0,0,0,0,9, - 12,1,114,81,0,0,0,99,0,0,0,0,0,0,0,0, - 0,0,0,0,4,0,0,0,64,0,0,0,115,136,0,0, - 0,101,0,90,1,100,0,90,2,100,1,90,3,101,4,100, - 2,100,3,132,0,131,1,90,5,101,6,100,19,100,5,100, - 6,132,1,131,1,90,7,101,6,100,20,100,7,100,8,132, - 1,131,1,90,8,101,6,100,9,100,10,132,0,131,1,90, - 9,101,6,100,11,100,12,132,0,131,1,90,10,101,6,101, - 11,100,13,100,14,132,0,131,1,131,1,90,12,101,6,101, - 11,100,15,100,16,132,0,131,1,131,1,90,13,101,6,101, - 11,100,17,100,18,132,0,131,1,131,1,90,14,101,6,101, - 15,131,1,90,16,100,4,83,0,41,21,218,15,66,117,105, - 108,116,105,110,73,109,112,111,114,116,101,114,122,144,77,101, - 116,97,32,112,97,116,104,32,105,109,112,111,114,116,32,102, - 111,114,32,98,117,105,108,116,45,105,110,32,109,111,100,117, - 108,101,115,46,10,10,32,32,32,32,65,108,108,32,109,101, - 116,104,111,100,115,32,97,114,101,32,101,105,116,104,101,114, - 32,99,108,97,115,115,32,111,114,32,115,116,97,116,105,99, - 32,109,101,116,104,111,100,115,32,116,111,32,97,118,111,105, - 100,32,116,104,101,32,110,101,101,100,32,116,111,10,32,32, - 32,32,105,110,115,116,97,110,116,105,97,116,101,32,116,104, - 101,32,99,108,97,115,115,46,10,10,32,32,32,32,99,1, - 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, - 0,0,0,115,12,0,0,0,100,1,160,0,124,0,106,1, - 161,1,83,0,41,2,122,115,82,101,116,117,114,110,32,114, - 101,112,114,32,102,111,114,32,116,104,101,32,109,111,100,117, - 108,101,46,10,10,32,32,32,32,32,32,32,32,84,104,101, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,84,104,101,32,105,109,112,111, - 114,116,32,109,97,99,104,105,110,101,114,121,32,100,111,101, - 115,32,116,104,101,32,106,111,98,32,105,116,115,101,108,102, - 46,10,10,32,32,32,32,32,32,32,32,122,24,60,109,111, - 100,117,108,101,32,123,33,114,125,32,40,98,117,105,108,116, - 45,105,110,41,62,41,2,114,38,0,0,0,114,1,0,0, - 0,41,1,114,83,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,86,0,0,0,186,2,0,0, - 115,2,0,0,0,0,7,122,27,66,117,105,108,116,105,110, - 73,109,112,111,114,116,101,114,46,109,111,100,117,108,101,95, - 114,101,112,114,78,99,4,0,0,0,0,0,0,0,4,0, - 0,0,5,0,0,0,67,0,0,0,115,44,0,0,0,124, - 2,100,0,107,9,114,12,100,0,83,0,116,0,160,1,124, - 1,161,1,114,36,116,2,124,1,124,0,100,1,100,2,141, - 3,83,0,100,0,83,0,100,0,83,0,41,3,78,122,8, - 98,117,105,108,116,45,105,110,41,1,114,103,0,0,0,41, - 3,114,49,0,0,0,90,10,105,115,95,98,117,105,108,116, - 105,110,114,78,0,0,0,41,4,218,3,99,108,115,114,71, - 0,0,0,218,4,112,97,116,104,218,6,116,97,114,103,101, - 116,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,9,102,105,110,100,95,115,112,101,99,195,2,0,0,115, - 10,0,0,0,0,2,8,1,4,1,10,1,14,2,122,25, - 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, - 102,105,110,100,95,115,112,101,99,99,3,0,0,0,0,0, - 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,30, - 0,0,0,124,0,160,0,124,1,124,2,161,2,125,3,124, - 3,100,1,107,9,114,26,124,3,106,1,83,0,100,1,83, - 0,41,2,122,175,70,105,110,100,32,116,104,101,32,98,117, - 105,108,116,45,105,110,32,109,111,100,117,108,101,46,10,10, - 32,32,32,32,32,32,32,32,73,102,32,39,112,97,116,104, - 39,32,105,115,32,101,118,101,114,32,115,112,101,99,105,102, - 105,101,100,32,116,104,101,110,32,116,104,101,32,115,101,97, - 114,99,104,32,105,115,32,99,111,110,115,105,100,101,114,101, - 100,32,97,32,102,97,105,108,117,114,101,46,10,10,32,32, + 0,0,114,11,0,0,0,218,14,95,108,111,97,100,95,117, + 110,108,111,99,107,101,100,139,2,0,0,115,20,0,0,0, + 0,2,10,2,12,1,8,2,8,1,10,1,10,1,10,1, + 16,3,22,5,114,140,0,0,0,99,1,0,0,0,0,0, + 0,0,1,0,0,0,9,0,0,0,67,0,0,0,115,30, + 0,0,0,116,0,124,0,106,1,131,1,143,10,1,0,116, + 2,124,0,131,1,83,0,81,0,82,0,88,0,100,1,83, + 0,41,2,122,191,82,101,116,117,114,110,32,97,32,110,101, + 119,32,109,111,100,117,108,101,32,111,98,106,101,99,116,44, + 32,108,111,97,100,101,100,32,98,121,32,116,104,101,32,115, + 112,101,99,39,115,32,108,111,97,100,101,114,46,10,10,32, + 32,32,32,84,104,101,32,109,111,100,117,108,101,32,105,115, + 32,110,111,116,32,97,100,100,101,100,32,116,111,32,105,116, + 115,32,112,97,114,101,110,116,46,10,10,32,32,32,32,73, + 102,32,97,32,109,111,100,117,108,101,32,105,115,32,97,108, + 114,101,97,100,121,32,105,110,32,115,121,115,46,109,111,100, + 117,108,101,115,44,32,116,104,97,116,32,101,120,105,115,116, + 105,110,103,32,109,111,100,117,108,101,32,103,101,116,115,10, + 32,32,32,32,99,108,111,98,98,101,114,101,100,46,10,10, + 32,32,32,32,78,41,3,114,42,0,0,0,114,15,0,0, + 0,114,140,0,0,0,41,1,114,82,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,81,0,0, + 0,162,2,0,0,115,4,0,0,0,0,9,12,1,114,81, + 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 4,0,0,0,64,0,0,0,115,136,0,0,0,101,0,90, + 1,100,0,90,2,100,1,90,3,101,4,100,2,100,3,132, + 0,131,1,90,5,101,6,100,19,100,5,100,6,132,1,131, + 1,90,7,101,6,100,20,100,7,100,8,132,1,131,1,90, + 8,101,6,100,9,100,10,132,0,131,1,90,9,101,6,100, + 11,100,12,132,0,131,1,90,10,101,6,101,11,100,13,100, + 14,132,0,131,1,131,1,90,12,101,6,101,11,100,15,100, + 16,132,0,131,1,131,1,90,13,101,6,101,11,100,17,100, + 18,132,0,131,1,131,1,90,14,101,6,101,15,131,1,90, + 16,100,4,83,0,41,21,218,15,66,117,105,108,116,105,110, + 73,109,112,111,114,116,101,114,122,144,77,101,116,97,32,112, + 97,116,104,32,105,109,112,111,114,116,32,102,111,114,32,98, + 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,46, + 10,10,32,32,32,32,65,108,108,32,109,101,116,104,111,100, + 115,32,97,114,101,32,101,105,116,104,101,114,32,99,108,97, + 115,115,32,111,114,32,115,116,97,116,105,99,32,109,101,116, + 104,111,100,115,32,116,111,32,97,118,111,105,100,32,116,104, + 101,32,110,101,101,100,32,116,111,10,32,32,32,32,105,110, + 115,116,97,110,116,105,97,116,101,32,116,104,101,32,99,108, + 97,115,115,46,10,10,32,32,32,32,99,1,0,0,0,0, + 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,115, + 12,0,0,0,100,1,160,0,124,0,106,1,161,1,83,0, + 41,2,122,115,82,101,116,117,114,110,32,114,101,112,114,32, + 102,111,114,32,116,104,101,32,109,111,100,117,108,101,46,10, + 10,32,32,32,32,32,32,32,32,84,104,101,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,84,104,101,32,105,109,112,111,114,116,32,109, + 97,99,104,105,110,101,114,121,32,100,111,101,115,32,116,104, + 101,32,106,111,98,32,105,116,115,101,108,102,46,10,10,32, + 32,32,32,32,32,32,32,122,24,60,109,111,100,117,108,101, + 32,123,33,114,125,32,40,98,117,105,108,116,45,105,110,41, + 62,41,2,114,38,0,0,0,114,1,0,0,0,41,1,114, + 83,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,86,0,0,0,186,2,0,0,115,2,0,0, + 0,0,7,122,27,66,117,105,108,116,105,110,73,109,112,111, + 114,116,101,114,46,109,111,100,117,108,101,95,114,101,112,114, + 78,99,4,0,0,0,0,0,0,0,4,0,0,0,5,0, + 0,0,67,0,0,0,115,44,0,0,0,124,2,100,0,107, + 9,114,12,100,0,83,0,116,0,160,1,124,1,161,1,114, + 36,116,2,124,1,124,0,100,1,100,2,141,3,83,0,100, + 0,83,0,100,0,83,0,41,3,78,122,8,98,117,105,108, + 116,45,105,110,41,1,114,103,0,0,0,41,3,114,49,0, + 0,0,90,10,105,115,95,98,117,105,108,116,105,110,114,78, + 0,0,0,41,4,218,3,99,108,115,114,71,0,0,0,218, + 4,112,97,116,104,218,6,116,97,114,103,101,116,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,9,102,105, + 110,100,95,115,112,101,99,195,2,0,0,115,10,0,0,0, + 0,2,8,1,4,1,10,1,14,2,122,25,66,117,105,108, + 116,105,110,73,109,112,111,114,116,101,114,46,102,105,110,100, + 95,115,112,101,99,99,3,0,0,0,0,0,0,0,4,0, + 0,0,4,0,0,0,67,0,0,0,115,30,0,0,0,124, + 0,160,0,124,1,124,2,161,2,125,3,124,3,100,1,107, + 9,114,26,124,3,106,1,83,0,100,1,83,0,41,2,122, + 175,70,105,110,100,32,116,104,101,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,46,10,10,32,32,32,32, + 32,32,32,32,73,102,32,39,112,97,116,104,39,32,105,115, + 32,101,118,101,114,32,115,112,101,99,105,102,105,101,100,32, + 116,104,101,110,32,116,104,101,32,115,101,97,114,99,104,32, + 105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,32, + 102,97,105,108,117,114,101,46,10,10,32,32,32,32,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,32,32,85,115, + 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, + 115,116,101,97,100,46,10,10,32,32,32,32,32,32,32,32, + 78,41,2,114,145,0,0,0,114,93,0,0,0,41,4,114, + 142,0,0,0,114,71,0,0,0,114,143,0,0,0,114,82, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,204, + 2,0,0,115,4,0,0,0,0,9,12,1,122,27,66,117, + 105,108,116,105,110,73,109,112,111,114,116,101,114,46,102,105, + 110,100,95,109,111,100,117,108,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,4,0,0,0,67,0,0,0,115,46, + 0,0,0,124,1,106,0,116,1,106,2,107,7,114,34,116, + 3,100,1,160,4,124,1,106,0,161,1,124,1,106,0,100, + 2,141,2,130,1,116,5,116,6,106,7,124,1,131,2,83, + 0,41,3,122,24,67,114,101,97,116,101,32,97,32,98,117, + 105,108,116,45,105,110,32,109,111,100,117,108,101,122,29,123, + 33,114,125,32,105,115,32,110,111,116,32,97,32,98,117,105, + 108,116,45,105,110,32,109,111,100,117,108,101,41,1,114,15, + 0,0,0,41,8,114,15,0,0,0,114,14,0,0,0,114, + 69,0,0,0,114,70,0,0,0,114,38,0,0,0,114,59, + 0,0,0,114,49,0,0,0,90,14,99,114,101,97,116,101, + 95,98,117,105,108,116,105,110,41,2,114,26,0,0,0,114, + 82,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,134,0,0,0,216,2,0,0,115,8,0,0, + 0,0,3,12,1,12,1,10,1,122,29,66,117,105,108,116, + 105,110,73,109,112,111,114,116,101,114,46,99,114,101,97,116, + 101,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, + 0,2,0,0,0,3,0,0,0,67,0,0,0,115,16,0, + 0,0,116,0,116,1,106,2,124,1,131,2,1,0,100,1, + 83,0,41,2,122,22,69,120,101,99,32,97,32,98,117,105, + 108,116,45,105,110,32,109,111,100,117,108,101,78,41,3,114, + 59,0,0,0,114,49,0,0,0,90,12,101,120,101,99,95, + 98,117,105,108,116,105,110,41,2,114,26,0,0,0,114,83, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,135,0,0,0,224,2,0,0,115,2,0,0,0, + 0,3,122,27,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,46,101,120,101,99,95,109,111,100,117,108,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, + 67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,122, + 57,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, + 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,115, + 32,100,111,32,110,111,116,32,104,97,118,101,32,99,111,100, + 101,32,111,98,106,101,99,116,115,46,78,114,10,0,0,0, + 41,2,114,142,0,0,0,114,71,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,218,8,103,101,116, + 95,99,111,100,101,229,2,0,0,115,2,0,0,0,0,4, + 122,24,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 114,46,103,101,116,95,99,111,100,101,99,2,0,0,0,0, + 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, + 4,0,0,0,100,1,83,0,41,2,122,56,82,101,116,117, + 114,110,32,78,111,110,101,32,97,115,32,98,117,105,108,116, + 45,105,110,32,109,111,100,117,108,101,115,32,100,111,32,110, + 111,116,32,104,97,118,101,32,115,111,117,114,99,101,32,99, + 111,100,101,46,78,114,10,0,0,0,41,2,114,142,0,0, + 0,114,71,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,10,103,101,116,95,115,111,117,114,99, + 101,235,2,0,0,115,2,0,0,0,0,4,122,26,66,117, + 105,108,116,105,110,73,109,112,111,114,116,101,114,46,103,101, + 116,95,115,111,117,114,99,101,99,2,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,115,4,0, + 0,0,100,1,83,0,41,2,122,52,82,101,116,117,114,110, + 32,70,97,108,115,101,32,97,115,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,115,32,97,114,101,32,110, + 101,118,101,114,32,112,97,99,107,97,103,101,115,46,70,114, + 10,0,0,0,41,2,114,142,0,0,0,114,71,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 105,0,0,0,241,2,0,0,115,2,0,0,0,0,4,122, + 26,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, + 46,105,115,95,112,97,99,107,97,103,101,41,2,78,78,41, + 1,78,41,17,114,1,0,0,0,114,0,0,0,0,114,2, + 0,0,0,114,3,0,0,0,218,12,115,116,97,116,105,99, + 109,101,116,104,111,100,114,86,0,0,0,218,11,99,108,97, + 115,115,109,101,116,104,111,100,114,145,0,0,0,114,146,0, + 0,0,114,134,0,0,0,114,135,0,0,0,114,74,0,0, + 0,114,147,0,0,0,114,148,0,0,0,114,105,0,0,0, + 114,84,0,0,0,114,137,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,141, + 0,0,0,177,2,0,0,115,28,0,0,0,12,9,12,9, + 2,1,12,8,2,1,12,11,12,8,12,5,2,1,14,5, + 2,1,14,5,2,1,14,5,114,141,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,4,0,0,0,64,0, + 0,0,115,140,0,0,0,101,0,90,1,100,0,90,2,100, + 1,90,3,101,4,100,2,100,3,132,0,131,1,90,5,101, + 6,100,21,100,5,100,6,132,1,131,1,90,7,101,6,100, + 22,100,7,100,8,132,1,131,1,90,8,101,6,100,9,100, + 10,132,0,131,1,90,9,101,4,100,11,100,12,132,0,131, + 1,90,10,101,6,100,13,100,14,132,0,131,1,90,11,101, + 6,101,12,100,15,100,16,132,0,131,1,131,1,90,13,101, + 6,101,12,100,17,100,18,132,0,131,1,131,1,90,14,101, + 6,101,12,100,19,100,20,132,0,131,1,131,1,90,15,100, + 4,83,0,41,23,218,14,70,114,111,122,101,110,73,109,112, + 111,114,116,101,114,122,142,77,101,116,97,32,112,97,116,104, + 32,105,109,112,111,114,116,32,102,111,114,32,102,114,111,122, + 101,110,32,109,111,100,117,108,101,115,46,10,10,32,32,32, + 32,65,108,108,32,109,101,116,104,111,100,115,32,97,114,101, + 32,101,105,116,104,101,114,32,99,108,97,115,115,32,111,114, + 32,115,116,97,116,105,99,32,109,101,116,104,111,100,115,32, + 116,111,32,97,118,111,105,100,32,116,104,101,32,110,101,101, + 100,32,116,111,10,32,32,32,32,105,110,115,116,97,110,116, + 105,97,116,101,32,116,104,101,32,99,108,97,115,115,46,10, + 10,32,32,32,32,99,1,0,0,0,0,0,0,0,1,0, + 0,0,3,0,0,0,67,0,0,0,115,12,0,0,0,100, + 1,160,0,124,0,106,1,161,1,83,0,41,2,122,115,82, + 101,116,117,114,110,32,114,101,112,114,32,102,111,114,32,116, + 104,101,32,109,111,100,117,108,101,46,10,10,32,32,32,32, + 32,32,32,32,84,104,101,32,109,101,116,104,111,100,32,105, + 115,32,100,101,112,114,101,99,97,116,101,100,46,32,32,84, + 104,101,32,105,109,112,111,114,116,32,109,97,99,104,105,110, + 101,114,121,32,100,111,101,115,32,116,104,101,32,106,111,98, + 32,105,116,115,101,108,102,46,10,10,32,32,32,32,32,32, + 32,32,122,22,60,109,111,100,117,108,101,32,123,33,114,125, + 32,40,102,114,111,122,101,110,41,62,41,2,114,38,0,0, + 0,114,1,0,0,0,41,1,218,1,109,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,86,0,0,0,3, + 3,0,0,115,2,0,0,0,0,7,122,26,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,46,109,111,100,117,108, + 101,95,114,101,112,114,78,99,4,0,0,0,0,0,0,0, + 4,0,0,0,5,0,0,0,67,0,0,0,115,32,0,0, + 0,116,0,160,1,124,1,161,1,114,24,116,2,124,1,124, + 0,100,1,100,2,141,3,83,0,100,0,83,0,100,0,83, + 0,41,3,78,90,6,102,114,111,122,101,110,41,1,114,103, + 0,0,0,41,3,114,49,0,0,0,114,75,0,0,0,114, + 78,0,0,0,41,4,114,142,0,0,0,114,71,0,0,0, + 114,143,0,0,0,114,144,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,145,0,0,0,12,3, + 0,0,115,6,0,0,0,0,2,10,1,14,2,122,24,70, + 114,111,122,101,110,73,109,112,111,114,116,101,114,46,102,105, + 110,100,95,115,112,101,99,99,3,0,0,0,0,0,0,0, + 3,0,0,0,3,0,0,0,67,0,0,0,115,18,0,0, + 0,116,0,160,1,124,1,161,1,114,14,124,0,83,0,100, + 1,83,0,41,2,122,93,70,105,110,100,32,97,32,102,114, + 111,122,101,110,32,109,111,100,117,108,101,46,10,10,32,32, 32,32,32,32,32,32,84,104,105,115,32,109,101,116,104,111, 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, 32,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 32,32,32,32,78,41,2,114,145,0,0,0,114,93,0,0, - 0,41,4,114,142,0,0,0,114,71,0,0,0,114,143,0, - 0,0,114,82,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,11,102,105,110,100,95,109,111,100, - 117,108,101,204,2,0,0,115,4,0,0,0,0,9,12,1, - 122,27,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 32,32,32,32,78,41,2,114,49,0,0,0,114,75,0,0, + 0,41,3,114,142,0,0,0,114,71,0,0,0,114,143,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,146,0,0,0,19,3,0,0,115,2,0,0,0,0, + 7,122,26,70,114,111,122,101,110,73,109,112,111,114,116,101, 114,46,102,105,110,100,95,109,111,100,117,108,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,4,0,0,0,67,0, - 0,0,115,46,0,0,0,124,1,106,0,116,1,106,2,107, - 7,114,34,116,3,100,1,160,4,124,1,106,0,161,1,124, - 1,106,0,100,2,141,2,130,1,116,5,116,6,106,7,124, - 1,131,2,83,0,41,3,122,24,67,114,101,97,116,101,32, - 97,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, - 101,122,29,123,33,114,125,32,105,115,32,110,111,116,32,97, - 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, - 41,1,114,15,0,0,0,41,8,114,15,0,0,0,114,14, - 0,0,0,114,69,0,0,0,114,70,0,0,0,114,38,0, - 0,0,114,59,0,0,0,114,49,0,0,0,90,14,99,114, - 101,97,116,101,95,98,117,105,108,116,105,110,41,2,114,26, - 0,0,0,114,82,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,134,0,0,0,216,2,0,0, - 115,8,0,0,0,0,3,12,1,12,1,10,1,122,29,66, - 117,105,108,116,105,110,73,109,112,111,114,116,101,114,46,99, - 114,101,97,116,101,95,109,111,100,117,108,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, - 0,115,16,0,0,0,116,0,116,1,106,2,124,1,131,2, - 1,0,100,1,83,0,41,2,122,22,69,120,101,99,32,97, - 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, - 78,41,3,114,59,0,0,0,114,49,0,0,0,90,12,101, - 120,101,99,95,98,117,105,108,116,105,110,41,2,114,26,0, - 0,0,114,83,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,135,0,0,0,224,2,0,0,115, - 2,0,0,0,0,3,122,27,66,117,105,108,116,105,110,73, - 109,112,111,114,116,101,114,46,101,120,101,99,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, - 0,41,2,122,57,82,101,116,117,114,110,32,78,111,110,101, - 32,97,115,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,115,32,100,111,32,110,111,116,32,104,97,118,101, - 32,99,111,100,101,32,111,98,106,101,99,116,115,46,78,114, - 10,0,0,0,41,2,114,142,0,0,0,114,71,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, - 8,103,101,116,95,99,111,100,101,229,2,0,0,115,2,0, - 0,0,0,4,122,24,66,117,105,108,116,105,110,73,109,112, - 111,114,116,101,114,46,103,101,116,95,99,111,100,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, - 0,0,0,115,4,0,0,0,100,1,83,0,41,2,122,56, - 82,101,116,117,114,110,32,78,111,110,101,32,97,115,32,98, - 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32, - 100,111,32,110,111,116,32,104,97,118,101,32,115,111,117,114, - 99,101,32,99,111,100,101,46,78,114,10,0,0,0,41,2, - 114,142,0,0,0,114,71,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,10,103,101,116,95,115, - 111,117,114,99,101,235,2,0,0,115,2,0,0,0,0,4, - 122,26,66,117,105,108,116,105,110,73,109,112,111,114,116,101, - 114,46,103,101,116,95,115,111,117,114,99,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,83,0,41,2,122,52,82,101, - 116,117,114,110,32,70,97,108,115,101,32,97,115,32,98,117, - 105,108,116,45,105,110,32,109,111,100,117,108,101,115,32,97, - 114,101,32,110,101,118,101,114,32,112,97,99,107,97,103,101, - 115,46,70,114,10,0,0,0,41,2,114,142,0,0,0,114, - 71,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,105,0,0,0,241,2,0,0,115,2,0,0, - 0,0,4,122,26,66,117,105,108,116,105,110,73,109,112,111, - 114,116,101,114,46,105,115,95,112,97,99,107,97,103,101,41, - 2,78,78,41,1,78,41,17,114,1,0,0,0,114,0,0, - 0,0,114,2,0,0,0,114,3,0,0,0,218,12,115,116, - 97,116,105,99,109,101,116,104,111,100,114,86,0,0,0,218, - 11,99,108,97,115,115,109,101,116,104,111,100,114,145,0,0, - 0,114,146,0,0,0,114,134,0,0,0,114,135,0,0,0, - 114,74,0,0,0,114,147,0,0,0,114,148,0,0,0,114, - 105,0,0,0,114,84,0,0,0,114,137,0,0,0,114,10, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,115,4,0,0,0,100,1,83,0,41,2,122,42,85, + 115,101,32,100,101,102,97,117,108,116,32,115,101,109,97,110, + 116,105,99,115,32,102,111,114,32,109,111,100,117,108,101,32, + 99,114,101,97,116,105,111,110,46,78,114,10,0,0,0,41, + 2,114,142,0,0,0,114,82,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,134,0,0,0,28, + 3,0,0,115,0,0,0,0,122,28,70,114,111,122,101,110, + 73,109,112,111,114,116,101,114,46,99,114,101,97,116,101,95, + 109,111,100,117,108,101,99,1,0,0,0,0,0,0,0,3, + 0,0,0,4,0,0,0,67,0,0,0,115,64,0,0,0, + 124,0,106,0,106,1,125,1,116,2,160,3,124,1,161,1, + 115,36,116,4,100,1,160,5,124,1,161,1,124,1,100,2, + 141,2,130,1,116,6,116,2,106,7,124,1,131,2,125,2, + 116,8,124,2,124,0,106,9,131,2,1,0,100,0,83,0, + 41,3,78,122,27,123,33,114,125,32,105,115,32,110,111,116, + 32,97,32,102,114,111,122,101,110,32,109,111,100,117,108,101, + 41,1,114,15,0,0,0,41,10,114,89,0,0,0,114,15, + 0,0,0,114,49,0,0,0,114,75,0,0,0,114,70,0, + 0,0,114,38,0,0,0,114,59,0,0,0,218,17,103,101, + 116,95,102,114,111,122,101,110,95,111,98,106,101,99,116,218, + 4,101,120,101,99,114,7,0,0,0,41,3,114,83,0,0, + 0,114,15,0,0,0,218,4,99,111,100,101,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,135,0,0,0, + 32,3,0,0,115,12,0,0,0,0,2,8,1,10,1,10, + 1,8,1,12,1,122,26,70,114,111,122,101,110,73,109,112, + 111,114,116,101,114,46,101,120,101,99,95,109,111,100,117,108, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,67,0,0,0,115,10,0,0,0,116,0,124,0,124, + 1,131,2,83,0,41,1,122,95,76,111,97,100,32,97,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, + 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,32,32,32,32,41,1,114,84,0,0,0,41, + 2,114,142,0,0,0,114,71,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,137,0,0,0,41, + 3,0,0,115,2,0,0,0,0,7,122,26,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,46,108,111,97,100,95, + 109,111,100,117,108,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,67,0,0,0,115,10,0,0,0, + 116,0,160,1,124,1,161,1,83,0,41,1,122,45,82,101, + 116,117,114,110,32,116,104,101,32,99,111,100,101,32,111,98, + 106,101,99,116,32,102,111,114,32,116,104,101,32,102,114,111, + 122,101,110,32,109,111,100,117,108,101,46,41,2,114,49,0, + 0,0,114,153,0,0,0,41,2,114,142,0,0,0,114,71, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,141,0,0,0,177,2,0,0,115,28,0,0,0, - 12,9,12,9,2,1,12,8,2,1,12,11,12,8,12,5, - 2,1,14,5,2,1,14,5,2,1,14,5,114,141,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,4,0, - 0,0,64,0,0,0,115,140,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,101,4,100,2,100,3,132,0,131, - 1,90,5,101,6,100,21,100,5,100,6,132,1,131,1,90, - 7,101,6,100,22,100,7,100,8,132,1,131,1,90,8,101, - 6,100,9,100,10,132,0,131,1,90,9,101,4,100,11,100, - 12,132,0,131,1,90,10,101,6,100,13,100,14,132,0,131, - 1,90,11,101,6,101,12,100,15,100,16,132,0,131,1,131, - 1,90,13,101,6,101,12,100,17,100,18,132,0,131,1,131, - 1,90,14,101,6,101,12,100,19,100,20,132,0,131,1,131, - 1,90,15,100,4,83,0,41,23,218,14,70,114,111,122,101, - 110,73,109,112,111,114,116,101,114,122,142,77,101,116,97,32, - 112,97,116,104,32,105,109,112,111,114,116,32,102,111,114,32, - 102,114,111,122,101,110,32,109,111,100,117,108,101,115,46,10, - 10,32,32,32,32,65,108,108,32,109,101,116,104,111,100,115, - 32,97,114,101,32,101,105,116,104,101,114,32,99,108,97,115, - 115,32,111,114,32,115,116,97,116,105,99,32,109,101,116,104, - 111,100,115,32,116,111,32,97,118,111,105,100,32,116,104,101, - 32,110,101,101,100,32,116,111,10,32,32,32,32,105,110,115, - 116,97,110,116,105,97,116,101,32,116,104,101,32,99,108,97, - 115,115,46,10,10,32,32,32,32,99,1,0,0,0,0,0, - 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,12, - 0,0,0,100,1,160,0,124,0,106,1,161,1,83,0,41, - 2,122,115,82,101,116,117,114,110,32,114,101,112,114,32,102, - 111,114,32,116,104,101,32,109,111,100,117,108,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,101,32,109,101,116,104, - 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, - 46,32,32,84,104,101,32,105,109,112,111,114,116,32,109,97, - 99,104,105,110,101,114,121,32,100,111,101,115,32,116,104,101, - 32,106,111,98,32,105,116,115,101,108,102,46,10,10,32,32, - 32,32,32,32,32,32,122,22,60,109,111,100,117,108,101,32, - 123,33,114,125,32,40,102,114,111,122,101,110,41,62,41,2, - 114,38,0,0,0,114,1,0,0,0,41,1,218,1,109,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,86, - 0,0,0,3,3,0,0,115,2,0,0,0,0,7,122,26, - 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,109, - 111,100,117,108,101,95,114,101,112,114,78,99,4,0,0,0, - 0,0,0,0,4,0,0,0,5,0,0,0,67,0,0,0, - 115,32,0,0,0,116,0,160,1,124,1,161,1,114,24,116, - 2,124,1,124,0,100,1,100,2,141,3,83,0,100,0,83, - 0,100,0,83,0,41,3,78,90,6,102,114,111,122,101,110, - 41,1,114,103,0,0,0,41,3,114,49,0,0,0,114,75, - 0,0,0,114,78,0,0,0,41,4,114,142,0,0,0,114, - 71,0,0,0,114,143,0,0,0,114,144,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,145,0, - 0,0,12,3,0,0,115,6,0,0,0,0,2,10,1,14, - 2,122,24,70,114,111,122,101,110,73,109,112,111,114,116,101, - 114,46,102,105,110,100,95,115,112,101,99,99,3,0,0,0, - 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, - 115,18,0,0,0,116,0,160,1,124,1,161,1,114,14,124, - 0,83,0,100,1,83,0,41,2,122,93,70,105,110,100,32, - 97,32,102,114,111,122,101,110,32,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,84,104,105,115,32,109, - 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,46,32,32,85,115,101,32,102,105,110,100,95,115, - 112,101,99,40,41,32,105,110,115,116,101,97,100,46,10,10, - 32,32,32,32,32,32,32,32,78,41,2,114,49,0,0,0, - 114,75,0,0,0,41,3,114,142,0,0,0,114,71,0,0, - 0,114,143,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,146,0,0,0,19,3,0,0,115,2, - 0,0,0,0,7,122,26,70,114,111,122,101,110,73,109,112, - 111,114,116,101,114,46,102,105,110,100,95,109,111,100,117,108, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,122,42,85,115,101,32,100,101,102,97,117,108,116,32,115, - 101,109,97,110,116,105,99,115,32,102,111,114,32,109,111,100, - 117,108,101,32,99,114,101,97,116,105,111,110,46,78,114,10, - 0,0,0,41,2,114,142,0,0,0,114,82,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,134, - 0,0,0,28,3,0,0,115,0,0,0,0,122,28,70,114, - 111,122,101,110,73,109,112,111,114,116,101,114,46,99,114,101, - 97,116,101,95,109,111,100,117,108,101,99,1,0,0,0,0, - 0,0,0,3,0,0,0,4,0,0,0,67,0,0,0,115, - 64,0,0,0,124,0,106,0,106,1,125,1,116,2,160,3, - 124,1,161,1,115,36,116,4,100,1,160,5,124,1,161,1, - 124,1,100,2,141,2,130,1,116,6,116,2,106,7,124,1, - 131,2,125,2,116,8,124,2,124,0,106,9,131,2,1,0, - 100,0,83,0,41,3,78,122,27,123,33,114,125,32,105,115, - 32,110,111,116,32,97,32,102,114,111,122,101,110,32,109,111, - 100,117,108,101,41,1,114,15,0,0,0,41,10,114,89,0, - 0,0,114,15,0,0,0,114,49,0,0,0,114,75,0,0, - 0,114,70,0,0,0,114,38,0,0,0,114,59,0,0,0, - 218,17,103,101,116,95,102,114,111,122,101,110,95,111,98,106, - 101,99,116,218,4,101,120,101,99,114,7,0,0,0,41,3, - 114,83,0,0,0,114,15,0,0,0,218,4,99,111,100,101, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 135,0,0,0,32,3,0,0,115,12,0,0,0,0,2,8, - 1,10,1,10,1,8,1,12,1,122,26,70,114,111,122,101, - 110,73,109,112,111,114,116,101,114,46,101,120,101,99,95,109, - 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,3,0,0,0,67,0,0,0,115,10,0,0,0,116, - 0,124,0,124,1,131,2,83,0,41,1,122,95,76,111,97, - 100,32,97,32,102,114,111,122,101,110,32,109,111,100,117,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, - 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, - 100,46,10,10,32,32,32,32,32,32,32,32,41,1,114,84, - 0,0,0,41,2,114,142,0,0,0,114,71,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,137, - 0,0,0,41,3,0,0,115,2,0,0,0,0,7,122,26, - 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,108, - 111,97,100,95,109,111,100,117,108,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, - 10,0,0,0,116,0,160,1,124,1,161,1,83,0,41,1, - 122,45,82,101,116,117,114,110,32,116,104,101,32,99,111,100, - 101,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101, - 32,102,114,111,122,101,110,32,109,111,100,117,108,101,46,41, - 2,114,49,0,0,0,114,153,0,0,0,41,2,114,142,0, - 0,0,114,71,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,147,0,0,0,50,3,0,0,115, - 2,0,0,0,0,4,122,23,70,114,111,122,101,110,73,109, - 112,111,114,116,101,114,46,103,101,116,95,99,111,100,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,122, - 54,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, - 102,114,111,122,101,110,32,109,111,100,117,108,101,115,32,100, - 111,32,110,111,116,32,104,97,118,101,32,115,111,117,114,99, - 101,32,99,111,100,101,46,78,114,10,0,0,0,41,2,114, - 142,0,0,0,114,71,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,148,0,0,0,56,3,0, - 0,115,2,0,0,0,0,4,122,25,70,114,111,122,101,110, - 73,109,112,111,114,116,101,114,46,103,101,116,95,115,111,117, - 114,99,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,67,0,0,0,115,10,0,0,0,116,0,160, - 1,124,1,161,1,83,0,41,1,122,46,82,101,116,117,114, - 110,32,84,114,117,101,32,105,102,32,116,104,101,32,102,114, - 111,122,101,110,32,109,111,100,117,108,101,32,105,115,32,97, - 32,112,97,99,107,97,103,101,46,41,2,114,49,0,0,0, - 90,17,105,115,95,102,114,111,122,101,110,95,112,97,99,107, - 97,103,101,41,2,114,142,0,0,0,114,71,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,105, - 0,0,0,62,3,0,0,115,2,0,0,0,0,4,122,25, - 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,105, - 115,95,112,97,99,107,97,103,101,41,2,78,78,41,1,78, - 41,16,114,1,0,0,0,114,0,0,0,0,114,2,0,0, - 0,114,3,0,0,0,114,149,0,0,0,114,86,0,0,0, - 114,150,0,0,0,114,145,0,0,0,114,146,0,0,0,114, - 134,0,0,0,114,135,0,0,0,114,137,0,0,0,114,77, - 0,0,0,114,147,0,0,0,114,148,0,0,0,114,105,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,151,0,0,0,250,2,0,0,115, - 28,0,0,0,12,9,12,9,2,1,12,6,2,1,12,8, - 12,4,12,9,12,9,2,1,14,5,2,1,14,5,2,1, - 114,151,0,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,64,0,0,0,115,32,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, - 0,90,4,100,4,100,5,132,0,90,5,100,6,83,0,41, - 7,218,18,95,73,109,112,111,114,116,76,111,99,107,67,111, - 110,116,101,120,116,122,36,67,111,110,116,101,120,116,32,109, - 97,110,97,103,101,114,32,102,111,114,32,116,104,101,32,105, - 109,112,111,114,116,32,108,111,99,107,46,99,1,0,0,0, - 0,0,0,0,1,0,0,0,2,0,0,0,67,0,0,0, - 115,12,0,0,0,116,0,160,1,161,0,1,0,100,1,83, - 0,41,2,122,24,65,99,113,117,105,114,101,32,116,104,101, - 32,105,109,112,111,114,116,32,108,111,99,107,46,78,41,2, - 114,49,0,0,0,114,50,0,0,0,41,1,114,26,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,46,0,0,0,75,3,0,0,115,2,0,0,0,0,2, - 122,28,95,73,109,112,111,114,116,76,111,99,107,67,111,110, - 116,101,120,116,46,95,95,101,110,116,101,114,95,95,99,4, - 0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,67, - 0,0,0,115,12,0,0,0,116,0,160,1,161,0,1,0, - 100,1,83,0,41,2,122,60,82,101,108,101,97,115,101,32, - 116,104,101,32,105,109,112,111,114,116,32,108,111,99,107,32, - 114,101,103,97,114,100,108,101,115,115,32,111,102,32,97,110, - 121,32,114,97,105,115,101,100,32,101,120,99,101,112,116,105, - 111,110,115,46,78,41,2,114,49,0,0,0,114,52,0,0, - 0,41,4,114,26,0,0,0,90,8,101,120,99,95,116,121, - 112,101,90,9,101,120,99,95,118,97,108,117,101,90,13,101, - 120,99,95,116,114,97,99,101,98,97,99,107,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,48,0,0,0, - 79,3,0,0,115,2,0,0,0,0,2,122,27,95,73,109, - 112,111,114,116,76,111,99,107,67,111,110,116,101,120,116,46, - 95,95,101,120,105,116,95,95,78,41,6,114,1,0,0,0, - 114,0,0,0,0,114,2,0,0,0,114,3,0,0,0,114, - 46,0,0,0,114,48,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,156,0, - 0,0,71,3,0,0,115,4,0,0,0,12,4,8,4,114, - 156,0,0,0,99,3,0,0,0,0,0,0,0,5,0,0, - 0,5,0,0,0,67,0,0,0,115,64,0,0,0,124,1, - 160,0,100,1,124,2,100,2,24,0,161,2,125,3,116,1, - 124,3,131,1,124,2,107,0,114,36,116,2,100,3,131,1, - 130,1,124,3,100,4,25,0,125,4,124,0,114,60,100,5, - 160,3,124,4,124,0,161,2,83,0,124,4,83,0,41,6, - 122,50,82,101,115,111,108,118,101,32,97,32,114,101,108,97, - 116,105,118,101,32,109,111,100,117,108,101,32,110,97,109,101, - 32,116,111,32,97,110,32,97,98,115,111,108,117,116,101,32, - 111,110,101,46,114,117,0,0,0,114,33,0,0,0,122,50, - 97,116,116,101,109,112,116,101,100,32,114,101,108,97,116,105, - 118,101,32,105,109,112,111,114,116,32,98,101,121,111,110,100, - 32,116,111,112,45,108,101,118,101,108,32,112,97,99,107,97, - 103,101,114,19,0,0,0,122,5,123,125,46,123,125,41,4, - 218,6,114,115,112,108,105,116,218,3,108,101,110,218,10,86, - 97,108,117,101,69,114,114,111,114,114,38,0,0,0,41,5, - 114,15,0,0,0,218,7,112,97,99,107,97,103,101,218,5, - 108,101,118,101,108,90,4,98,105,116,115,90,4,98,97,115, - 101,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,13,95,114,101,115,111,108,118,101,95,110,97,109,101,84, - 3,0,0,115,10,0,0,0,0,2,16,1,12,1,8,1, - 8,1,114,162,0,0,0,99,3,0,0,0,0,0,0,0, - 4,0,0,0,4,0,0,0,67,0,0,0,115,34,0,0, - 0,124,0,160,0,124,1,124,2,161,2,125,3,124,3,100, - 0,107,8,114,24,100,0,83,0,116,1,124,1,124,3,131, - 2,83,0,41,1,78,41,2,114,146,0,0,0,114,78,0, - 0,0,41,4,218,6,102,105,110,100,101,114,114,15,0,0, - 0,114,143,0,0,0,114,93,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,218,17,95,102,105,110, - 100,95,115,112,101,99,95,108,101,103,97,99,121,93,3,0, - 0,115,8,0,0,0,0,3,12,1,8,1,4,1,114,164, - 0,0,0,99,3,0,0,0,0,0,0,0,10,0,0,0, - 27,0,0,0,67,0,0,0,115,240,0,0,0,116,0,106, - 1,125,3,124,3,100,1,107,8,114,22,116,2,100,2,131, - 1,130,1,124,3,115,38,116,3,160,4,100,3,116,5,161, - 2,1,0,124,0,116,0,106,6,107,6,125,4,120,186,124, - 3,68,0,93,174,125,5,116,7,131,0,143,72,1,0,121, - 10,124,5,106,8,125,6,87,0,110,42,4,0,116,9,107, - 10,114,118,1,0,1,0,1,0,116,10,124,5,124,0,124, - 1,131,3,125,7,124,7,100,1,107,8,114,114,119,54,89, - 0,110,14,88,0,124,6,124,0,124,1,124,2,131,3,125, - 7,87,0,100,1,81,0,82,0,88,0,124,7,100,1,107, - 9,114,54,124,4,115,224,124,0,116,0,106,6,107,6,114, - 224,116,0,106,6,124,0,25,0,125,8,121,10,124,8,106, - 11,125,9,87,0,110,20,4,0,116,9,107,10,114,204,1, - 0,1,0,1,0,124,7,83,0,88,0,124,9,100,1,107, - 8,114,218,124,7,83,0,124,9,83,0,113,54,124,7,83, - 0,113,54,87,0,100,1,83,0,100,1,83,0,41,4,122, - 21,70,105,110,100,32,97,32,109,111,100,117,108,101,39,115, - 32,115,112,101,99,46,78,122,53,115,121,115,46,109,101,116, - 97,95,112,97,116,104,32,105,115,32,78,111,110,101,44,32, - 80,121,116,104,111,110,32,105,115,32,108,105,107,101,108,121, - 32,115,104,117,116,116,105,110,103,32,100,111,119,110,122,22, - 115,121,115,46,109,101,116,97,95,112,97,116,104,32,105,115, - 32,101,109,112,116,121,41,12,114,14,0,0,0,218,9,109, - 101,116,97,95,112,97,116,104,114,70,0,0,0,218,9,95, - 119,97,114,110,105,110,103,115,218,4,119,97,114,110,218,13, - 73,109,112,111,114,116,87,97,114,110,105,110,103,114,79,0, - 0,0,114,156,0,0,0,114,145,0,0,0,114,90,0,0, - 0,114,164,0,0,0,114,89,0,0,0,41,10,114,15,0, - 0,0,114,143,0,0,0,114,144,0,0,0,114,165,0,0, - 0,90,9,105,115,95,114,101,108,111,97,100,114,163,0,0, - 0,114,145,0,0,0,114,82,0,0,0,114,83,0,0,0, - 114,89,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,10,95,102,105,110,100,95,115,112,101,99, - 102,3,0,0,115,54,0,0,0,0,2,6,1,8,2,8, - 3,4,1,12,5,10,1,10,1,8,1,2,1,10,1,14, - 1,12,1,8,1,8,2,22,1,8,2,14,1,10,1,2, - 1,10,1,14,4,6,2,8,1,4,2,6,2,8,2,114, - 169,0,0,0,99,3,0,0,0,0,0,0,0,3,0,0, - 0,5,0,0,0,67,0,0,0,115,108,0,0,0,116,0, - 124,0,116,1,131,2,115,28,116,2,100,1,160,3,116,4, - 124,0,131,1,161,1,131,1,130,1,124,2,100,2,107,0, - 114,44,116,5,100,3,131,1,130,1,124,2,100,2,107,4, - 114,84,116,0,124,1,116,1,131,2,115,72,116,2,100,4, - 131,1,130,1,110,12,124,1,115,84,116,6,100,5,131,1, - 130,1,124,0,115,104,124,2,100,2,107,2,114,104,116,5, - 100,6,131,1,130,1,100,7,83,0,41,8,122,28,86,101, - 114,105,102,121,32,97,114,103,117,109,101,110,116,115,32,97, - 114,101,32,34,115,97,110,101,34,46,122,31,109,111,100,117, - 108,101,32,110,97,109,101,32,109,117,115,116,32,98,101,32, - 115,116,114,44,32,110,111,116,32,123,125,114,19,0,0,0, - 122,18,108,101,118,101,108,32,109,117,115,116,32,98,101,32, - 62,61,32,48,122,31,95,95,112,97,99,107,97,103,101,95, - 95,32,110,111,116,32,115,101,116,32,116,111,32,97,32,115, - 116,114,105,110,103,122,54,97,116,116,101,109,112,116,101,100, - 32,114,101,108,97,116,105,118,101,32,105,109,112,111,114,116, - 32,119,105,116,104,32,110,111,32,107,110,111,119,110,32,112, - 97,114,101,110,116,32,112,97,99,107,97,103,101,122,17,69, - 109,112,116,121,32,109,111,100,117,108,101,32,110,97,109,101, - 78,41,7,218,10,105,115,105,110,115,116,97,110,99,101,218, - 3,115,116,114,218,9,84,121,112,101,69,114,114,111,114,114, - 38,0,0,0,114,13,0,0,0,114,159,0,0,0,114,70, - 0,0,0,41,3,114,15,0,0,0,114,160,0,0,0,114, - 161,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,218,13,95,115,97,110,105,116,121,95,99,104,101, - 99,107,149,3,0,0,115,22,0,0,0,0,2,10,1,18, - 1,8,1,8,1,8,1,10,1,10,1,4,1,8,2,12, - 1,114,173,0,0,0,122,16,78,111,32,109,111,100,117,108, - 101,32,110,97,109,101,100,32,122,4,123,33,114,125,99,2, - 0,0,0,0,0,0,0,8,0,0,0,13,0,0,0,67, - 0,0,0,115,220,0,0,0,100,0,125,2,124,0,160,0, - 100,1,161,1,100,2,25,0,125,3,124,3,114,134,124,3, - 116,1,106,2,107,7,114,42,116,3,124,1,124,3,131,2, - 1,0,124,0,116,1,106,2,107,6,114,62,116,1,106,2, - 124,0,25,0,83,0,116,1,106,2,124,3,25,0,125,4, - 121,10,124,4,106,4,125,2,87,0,110,50,4,0,116,5, - 107,10,114,132,1,0,1,0,1,0,116,6,100,3,23,0, - 160,7,124,0,124,3,161,2,125,5,116,8,124,5,124,0, - 100,4,141,2,100,0,130,2,89,0,110,2,88,0,116,9, - 124,0,124,2,131,2,125,6,124,6,100,0,107,8,114,172, - 116,8,116,6,160,7,124,0,161,1,124,0,100,4,141,2, - 130,1,110,8,116,10,124,6,131,1,125,7,124,3,114,216, - 116,1,106,2,124,3,25,0,125,4,116,11,124,4,124,0, - 160,0,100,1,161,1,100,5,25,0,124,7,131,3,1,0, - 124,7,83,0,41,6,78,114,117,0,0,0,114,19,0,0, - 0,122,23,59,32,123,33,114,125,32,105,115,32,110,111,116, - 32,97,32,112,97,99,107,97,103,101,41,1,114,15,0,0, - 0,233,2,0,0,0,41,12,114,118,0,0,0,114,14,0, - 0,0,114,79,0,0,0,114,59,0,0,0,114,127,0,0, - 0,114,90,0,0,0,218,8,95,69,82,82,95,77,83,71, - 114,38,0,0,0,218,19,77,111,100,117,108,101,78,111,116, - 70,111,117,110,100,69,114,114,111,114,114,169,0,0,0,114, - 140,0,0,0,114,5,0,0,0,41,8,114,15,0,0,0, - 218,7,105,109,112,111,114,116,95,114,143,0,0,0,114,119, - 0,0,0,90,13,112,97,114,101,110,116,95,109,111,100,117, - 108,101,114,138,0,0,0,114,82,0,0,0,114,83,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,23,95,102,105,110,100,95,97,110,100,95,108,111,97,100, - 95,117,110,108,111,99,107,101,100,168,3,0,0,115,42,0, - 0,0,0,1,4,1,14,1,4,1,10,1,10,2,10,1, - 10,1,10,1,2,1,10,1,14,1,16,1,20,1,10,1, - 8,1,20,2,8,1,4,2,10,1,22,1,114,178,0,0, - 0,99,2,0,0,0,0,0,0,0,4,0,0,0,11,0, - 0,0,67,0,0,0,115,94,0,0,0,116,0,124,0,131, - 1,143,38,1,0,116,1,106,2,160,3,124,0,116,4,161, - 2,125,2,124,2,116,4,107,8,114,42,116,5,124,0,124, - 1,131,2,83,0,87,0,100,1,81,0,82,0,88,0,124, - 2,100,1,107,8,114,82,100,2,160,6,124,0,161,1,125, - 3,116,7,124,3,124,0,100,3,141,2,130,1,116,8,124, - 0,131,1,1,0,124,2,83,0,41,4,122,25,70,105,110, - 100,32,97,110,100,32,108,111,97,100,32,116,104,101,32,109, - 111,100,117,108,101,46,78,122,40,105,109,112,111,114,116,32, - 111,102,32,123,125,32,104,97,108,116,101,100,59,32,78,111, - 110,101,32,105,110,32,115,121,115,46,109,111,100,117,108,101, - 115,41,1,114,15,0,0,0,41,9,114,42,0,0,0,114, - 14,0,0,0,114,79,0,0,0,114,30,0,0,0,218,14, - 95,78,69,69,68,83,95,76,79,65,68,73,78,71,114,178, - 0,0,0,114,38,0,0,0,114,176,0,0,0,114,57,0, - 0,0,41,4,114,15,0,0,0,114,177,0,0,0,114,83, - 0,0,0,114,67,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,14,95,102,105,110,100,95,97, - 110,100,95,108,111,97,100,198,3,0,0,115,20,0,0,0, - 0,2,10,1,14,1,8,1,20,2,8,1,4,1,6,1, - 12,2,8,1,114,180,0,0,0,114,19,0,0,0,99,3, - 0,0,0,0,0,0,0,3,0,0,0,4,0,0,0,67, - 0,0,0,115,42,0,0,0,116,0,124,0,124,1,124,2, - 131,3,1,0,124,2,100,1,107,4,114,32,116,1,124,0, - 124,1,124,2,131,3,125,0,116,2,124,0,116,3,131,2, - 83,0,41,2,97,50,1,0,0,73,109,112,111,114,116,32, - 97,110,100,32,114,101,116,117,114,110,32,116,104,101,32,109, - 111,100,117,108,101,32,98,97,115,101,100,32,111,110,32,105, - 116,115,32,110,97,109,101,44,32,116,104,101,32,112,97,99, - 107,97,103,101,32,116,104,101,32,99,97,108,108,32,105,115, - 10,32,32,32,32,98,101,105,110,103,32,109,97,100,101,32, - 102,114,111,109,44,32,97,110,100,32,116,104,101,32,108,101, - 118,101,108,32,97,100,106,117,115,116,109,101,110,116,46,10, - 10,32,32,32,32,84,104,105,115,32,102,117,110,99,116,105, - 111,110,32,114,101,112,114,101,115,101,110,116,115,32,116,104, - 101,32,103,114,101,97,116,101,115,116,32,99,111,109,109,111, - 110,32,100,101,110,111,109,105,110,97,116,111,114,32,111,102, - 32,102,117,110,99,116,105,111,110,97,108,105,116,121,10,32, - 32,32,32,98,101,116,119,101,101,110,32,105,109,112,111,114, - 116,95,109,111,100,117,108,101,32,97,110,100,32,95,95,105, - 109,112,111,114,116,95,95,46,32,84,104,105,115,32,105,110, - 99,108,117,100,101,115,32,115,101,116,116,105,110,103,32,95, - 95,112,97,99,107,97,103,101,95,95,32,105,102,10,32,32, - 32,32,116,104,101,32,108,111,97,100,101,114,32,100,105,100, - 32,110,111,116,46,10,10,32,32,32,32,114,19,0,0,0, - 41,4,114,173,0,0,0,114,162,0,0,0,114,180,0,0, - 0,218,11,95,103,99,100,95,105,109,112,111,114,116,41,3, - 114,15,0,0,0,114,160,0,0,0,114,161,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,181, - 0,0,0,214,3,0,0,115,8,0,0,0,0,9,12,1, - 8,1,12,1,114,181,0,0,0,41,1,218,9,114,101,99, - 117,114,115,105,118,101,99,3,0,0,0,1,0,0,0,8, - 0,0,0,17,0,0,0,67,0,0,0,115,234,0,0,0, - 116,0,124,0,100,1,131,2,114,230,120,218,124,1,68,0, - 93,210,125,4,116,1,124,4,116,2,131,2,115,78,124,3, - 114,46,124,0,106,3,100,2,23,0,125,5,110,4,100,3, - 125,5,116,4,100,4,124,5,155,0,100,5,116,5,124,4, - 131,1,106,3,155,0,157,4,131,1,130,1,113,16,124,4, - 100,6,107,2,114,120,124,3,115,226,116,0,124,0,100,7, - 131,2,114,226,116,6,124,0,124,0,106,7,124,2,100,8, - 100,9,141,4,1,0,113,16,116,0,124,0,124,4,131,2, - 115,16,100,10,160,8,124,0,106,3,124,4,161,2,125,6, - 121,14,116,9,124,2,124,6,131,2,1,0,87,0,113,16, - 4,0,116,10,107,10,114,224,1,0,125,7,1,0,122,38, - 124,7,106,11,124,6,107,2,114,206,116,12,106,13,160,14, - 124,6,116,15,161,2,100,11,107,9,114,206,119,16,130,0, - 87,0,89,0,100,11,100,11,125,7,126,7,88,0,113,16, - 88,0,113,16,87,0,124,0,83,0,41,12,122,238,70,105, - 103,117,114,101,32,111,117,116,32,119,104,97,116,32,95,95, - 105,109,112,111,114,116,95,95,32,115,104,111,117,108,100,32, - 114,101,116,117,114,110,46,10,10,32,32,32,32,84,104,101, - 32,105,109,112,111,114,116,95,32,112,97,114,97,109,101,116, - 101,114,32,105,115,32,97,32,99,97,108,108,97,98,108,101, - 32,119,104,105,99,104,32,116,97,107,101,115,32,116,104,101, - 32,110,97,109,101,32,111,102,32,109,111,100,117,108,101,32, - 116,111,10,32,32,32,32,105,109,112,111,114,116,46,32,73, - 116,32,105,115,32,114,101,113,117,105,114,101,100,32,116,111, - 32,100,101,99,111,117,112,108,101,32,116,104,101,32,102,117, - 110,99,116,105,111,110,32,102,114,111,109,32,97,115,115,117, - 109,105,110,103,32,105,109,112,111,114,116,108,105,98,39,115, - 10,32,32,32,32,105,109,112,111,114,116,32,105,109,112,108, - 101,109,101,110,116,97,116,105,111,110,32,105,115,32,100,101, - 115,105,114,101,100,46,10,10,32,32,32,32,114,127,0,0, - 0,122,8,46,95,95,97,108,108,95,95,122,13,96,96,102, - 114,111,109,32,108,105,115,116,39,39,122,8,73,116,101,109, - 32,105,110,32,122,18,32,109,117,115,116,32,98,101,32,115, - 116,114,44,32,110,111,116,32,250,1,42,218,7,95,95,97, - 108,108,95,95,84,41,1,114,182,0,0,0,122,5,123,125, - 46,123,125,78,41,16,114,4,0,0,0,114,170,0,0,0, - 114,171,0,0,0,114,1,0,0,0,114,172,0,0,0,114, - 13,0,0,0,218,16,95,104,97,110,100,108,101,95,102,114, - 111,109,108,105,115,116,114,184,0,0,0,114,38,0,0,0, - 114,59,0,0,0,114,176,0,0,0,114,15,0,0,0,114, - 14,0,0,0,114,79,0,0,0,114,30,0,0,0,114,179, - 0,0,0,41,8,114,83,0,0,0,218,8,102,114,111,109, - 108,105,115,116,114,177,0,0,0,114,182,0,0,0,218,1, - 120,90,5,119,104,101,114,101,90,9,102,114,111,109,95,110, - 97,109,101,90,3,101,120,99,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,185,0,0,0,229,3,0,0, - 115,42,0,0,0,0,10,10,1,10,1,10,1,4,1,12, - 2,4,1,28,2,8,1,14,1,10,1,10,1,10,1,14, - 1,2,1,14,1,16,4,10,1,18,1,2,1,24,1,114, - 185,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0, - 0,6,0,0,0,67,0,0,0,115,146,0,0,0,124,0, - 160,0,100,1,161,1,125,1,124,0,160,0,100,2,161,1, - 125,2,124,1,100,3,107,9,114,82,124,2,100,3,107,9, - 114,78,124,1,124,2,106,1,107,3,114,78,116,2,106,3, - 100,4,124,1,155,2,100,5,124,2,106,1,155,2,100,6, - 157,5,116,4,100,7,100,8,141,3,1,0,124,1,83,0, - 124,2,100,3,107,9,114,96,124,2,106,1,83,0,116,2, - 106,3,100,9,116,4,100,7,100,8,141,3,1,0,124,0, - 100,10,25,0,125,1,100,11,124,0,107,7,114,142,124,1, - 160,5,100,12,161,1,100,13,25,0,125,1,124,1,83,0, - 41,14,122,167,67,97,108,99,117,108,97,116,101,32,119,104, - 97,116,32,95,95,112,97,99,107,97,103,101,95,95,32,115, - 104,111,117,108,100,32,98,101,46,10,10,32,32,32,32,95, - 95,112,97,99,107,97,103,101,95,95,32,105,115,32,110,111, - 116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32, - 98,101,32,100,101,102,105,110,101,100,32,111,114,32,99,111, - 117,108,100,32,98,101,32,115,101,116,32,116,111,32,78,111, - 110,101,10,32,32,32,32,116,111,32,114,101,112,114,101,115, - 101,110,116,32,116,104,97,116,32,105,116,115,32,112,114,111, - 112,101,114,32,118,97,108,117,101,32,105,115,32,117,110,107, - 110,111,119,110,46,10,10,32,32,32,32,114,130,0,0,0, - 114,89,0,0,0,78,122,32,95,95,112,97,99,107,97,103, - 101,95,95,32,33,61,32,95,95,115,112,101,99,95,95,46, - 112,97,114,101,110,116,32,40,122,4,32,33,61,32,250,1, - 41,233,3,0,0,0,41,1,90,10,115,116,97,99,107,108, - 101,118,101,108,122,89,99,97,110,39,116,32,114,101,115,111, - 108,118,101,32,112,97,99,107,97,103,101,32,102,114,111,109, - 32,95,95,115,112,101,99,95,95,32,111,114,32,95,95,112, - 97,99,107,97,103,101,95,95,44,32,102,97,108,108,105,110, - 103,32,98,97,99,107,32,111,110,32,95,95,110,97,109,101, - 95,95,32,97,110,100,32,95,95,112,97,116,104,95,95,114, - 1,0,0,0,114,127,0,0,0,114,117,0,0,0,114,19, - 0,0,0,41,6,114,30,0,0,0,114,119,0,0,0,114, - 166,0,0,0,114,167,0,0,0,114,168,0,0,0,114,118, - 0,0,0,41,3,218,7,103,108,111,98,97,108,115,114,160, - 0,0,0,114,82,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,17,95,99,97,108,99,95,95, - 95,112,97,99,107,97,103,101,95,95,11,4,0,0,115,30, - 0,0,0,0,7,10,1,10,1,8,1,18,1,22,2,10, - 1,4,1,8,1,6,2,6,2,10,1,8,1,8,1,14, - 1,114,191,0,0,0,114,10,0,0,0,99,5,0,0,0, - 0,0,0,0,9,0,0,0,5,0,0,0,67,0,0,0, - 115,166,0,0,0,124,4,100,1,107,2,114,18,116,0,124, - 0,131,1,125,5,110,36,124,1,100,2,107,9,114,30,124, - 1,110,2,105,0,125,6,116,1,124,6,131,1,125,7,116, - 0,124,0,124,7,124,4,131,3,125,5,124,3,115,150,124, - 4,100,1,107,2,114,84,116,0,124,0,160,2,100,3,161, - 1,100,1,25,0,131,1,83,0,124,0,115,92,124,5,83, - 0,116,3,124,0,131,1,116,3,124,0,160,2,100,3,161, - 1,100,1,25,0,131,1,24,0,125,8,116,4,106,5,124, - 5,106,6,100,2,116,3,124,5,106,6,131,1,124,8,24, - 0,133,2,25,0,25,0,83,0,110,12,116,7,124,5,124, - 3,116,0,131,3,83,0,100,2,83,0,41,4,97,215,1, - 0,0,73,109,112,111,114,116,32,97,32,109,111,100,117,108, - 101,46,10,10,32,32,32,32,84,104,101,32,39,103,108,111, - 98,97,108,115,39,32,97,114,103,117,109,101,110,116,32,105, - 115,32,117,115,101,100,32,116,111,32,105,110,102,101,114,32, - 119,104,101,114,101,32,116,104,101,32,105,109,112,111,114,116, - 32,105,115,32,111,99,99,117,114,114,105,110,103,32,102,114, - 111,109,10,32,32,32,32,116,111,32,104,97,110,100,108,101, - 32,114,101,108,97,116,105,118,101,32,105,109,112,111,114,116, - 115,46,32,84,104,101,32,39,108,111,99,97,108,115,39,32, - 97,114,103,117,109,101,110,116,32,105,115,32,105,103,110,111, - 114,101,100,46,32,84,104,101,10,32,32,32,32,39,102,114, - 111,109,108,105,115,116,39,32,97,114,103,117,109,101,110,116, - 32,115,112,101,99,105,102,105,101,115,32,119,104,97,116,32, - 115,104,111,117,108,100,32,101,120,105,115,116,32,97,115,32, - 97,116,116,114,105,98,117,116,101,115,32,111,110,32,116,104, - 101,32,109,111,100,117,108,101,10,32,32,32,32,98,101,105, - 110,103,32,105,109,112,111,114,116,101,100,32,40,101,46,103, - 46,32,96,96,102,114,111,109,32,109,111,100,117,108,101,32, - 105,109,112,111,114,116,32,60,102,114,111,109,108,105,115,116, - 62,96,96,41,46,32,32,84,104,101,32,39,108,101,118,101, - 108,39,10,32,32,32,32,97,114,103,117,109,101,110,116,32, - 114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,112, - 97,99,107,97,103,101,32,108,111,99,97,116,105,111,110,32, - 116,111,32,105,109,112,111,114,116,32,102,114,111,109,32,105, - 110,32,97,32,114,101,108,97,116,105,118,101,10,32,32,32, - 32,105,109,112,111,114,116,32,40,101,46,103,46,32,96,96, - 102,114,111,109,32,46,46,112,107,103,32,105,109,112,111,114, - 116,32,109,111,100,96,96,32,119,111,117,108,100,32,104,97, - 118,101,32,97,32,39,108,101,118,101,108,39,32,111,102,32, - 50,41,46,10,10,32,32,32,32,114,19,0,0,0,78,114, - 117,0,0,0,41,8,114,181,0,0,0,114,191,0,0,0, - 218,9,112,97,114,116,105,116,105,111,110,114,158,0,0,0, - 114,14,0,0,0,114,79,0,0,0,114,1,0,0,0,114, - 185,0,0,0,41,9,114,15,0,0,0,114,190,0,0,0, - 218,6,108,111,99,97,108,115,114,186,0,0,0,114,161,0, - 0,0,114,83,0,0,0,90,8,103,108,111,98,97,108,115, - 95,114,160,0,0,0,90,7,99,117,116,95,111,102,102,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,10, - 95,95,105,109,112,111,114,116,95,95,38,4,0,0,115,26, - 0,0,0,0,11,8,1,10,2,16,1,8,1,12,1,4, - 3,8,1,18,1,4,1,4,4,26,3,32,2,114,194,0, - 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,67,0,0,0,115,38,0,0,0,116,0,160,1, - 124,0,161,1,125,1,124,1,100,0,107,8,114,30,116,2, - 100,1,124,0,23,0,131,1,130,1,116,3,124,1,131,1, - 83,0,41,2,78,122,25,110,111,32,98,117,105,108,116,45, - 105,110,32,109,111,100,117,108,101,32,110,97,109,101,100,32, - 41,4,114,141,0,0,0,114,145,0,0,0,114,70,0,0, - 0,114,140,0,0,0,41,2,114,15,0,0,0,114,82,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,18,95,98,117,105,108,116,105,110,95,102,114,111,109, - 95,110,97,109,101,73,4,0,0,115,8,0,0,0,0,1, - 10,1,8,1,12,1,114,195,0,0,0,99,2,0,0,0, - 0,0,0,0,10,0,0,0,5,0,0,0,67,0,0,0, - 115,174,0,0,0,124,1,97,0,124,0,97,1,116,2,116, - 1,131,1,125,2,120,86,116,1,106,3,160,4,161,0,68, - 0,93,72,92,2,125,3,125,4,116,5,124,4,124,2,131, - 2,114,28,124,3,116,1,106,6,107,6,114,62,116,7,125, - 5,110,18,116,0,160,8,124,3,161,1,114,28,116,9,125, - 5,110,2,113,28,116,10,124,4,124,5,131,2,125,6,116, - 11,124,6,124,4,131,2,1,0,113,28,87,0,116,1,106, - 3,116,12,25,0,125,7,120,54,100,1,68,0,93,46,125, - 8,124,8,116,1,106,3,107,7,114,144,116,13,124,8,131, - 1,125,9,110,10,116,1,106,3,124,8,25,0,125,9,116, - 14,124,7,124,8,124,9,131,3,1,0,113,120,87,0,100, - 2,83,0,41,3,122,250,83,101,116,117,112,32,105,109,112, - 111,114,116,108,105,98,32,98,121,32,105,109,112,111,114,116, - 105,110,103,32,110,101,101,100,101,100,32,98,117,105,108,116, - 45,105,110,32,109,111,100,117,108,101,115,32,97,110,100,32, - 105,110,106,101,99,116,105,110,103,32,116,104,101,109,10,32, - 32,32,32,105,110,116,111,32,116,104,101,32,103,108,111,98, - 97,108,32,110,97,109,101,115,112,97,99,101,46,10,10,32, - 32,32,32,65,115,32,115,121,115,32,105,115,32,110,101,101, - 100,101,100,32,102,111,114,32,115,121,115,46,109,111,100,117, - 108,101,115,32,97,99,99,101,115,115,32,97,110,100,32,95, - 105,109,112,32,105,115,32,110,101,101,100,101,100,32,116,111, - 32,108,111,97,100,32,98,117,105,108,116,45,105,110,10,32, - 32,32,32,109,111,100,117,108,101,115,44,32,116,104,111,115, - 101,32,116,119,111,32,109,111,100,117,108,101,115,32,109,117, - 115,116,32,98,101,32,101,120,112,108,105,99,105,116,108,121, - 32,112,97,115,115,101,100,32,105,110,46,10,10,32,32,32, - 32,41,3,114,20,0,0,0,114,166,0,0,0,114,56,0, - 0,0,78,41,15,114,49,0,0,0,114,14,0,0,0,114, - 13,0,0,0,114,79,0,0,0,218,5,105,116,101,109,115, - 114,170,0,0,0,114,69,0,0,0,114,141,0,0,0,114, - 75,0,0,0,114,151,0,0,0,114,128,0,0,0,114,133, - 0,0,0,114,1,0,0,0,114,195,0,0,0,114,5,0, - 0,0,41,10,218,10,115,121,115,95,109,111,100,117,108,101, - 218,11,95,105,109,112,95,109,111,100,117,108,101,90,11,109, - 111,100,117,108,101,95,116,121,112,101,114,15,0,0,0,114, - 83,0,0,0,114,93,0,0,0,114,82,0,0,0,90,11, - 115,101,108,102,95,109,111,100,117,108,101,90,12,98,117,105, - 108,116,105,110,95,110,97,109,101,90,14,98,117,105,108,116, - 105,110,95,109,111,100,117,108,101,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,6,95,115,101,116,117,112, - 80,4,0,0,115,36,0,0,0,0,9,4,1,4,3,8, - 1,20,1,10,1,10,1,6,1,10,1,6,2,2,1,10, - 1,14,3,10,1,10,1,10,1,10,2,10,1,114,199,0, - 0,0,99,2,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,67,0,0,0,115,38,0,0,0,116,0,124,0, - 124,1,131,2,1,0,116,1,106,2,160,3,116,4,161,1, - 1,0,116,1,106,2,160,3,116,5,161,1,1,0,100,1, - 83,0,41,2,122,48,73,110,115,116,97,108,108,32,105,109, - 112,111,114,116,101,114,115,32,102,111,114,32,98,117,105,108, - 116,105,110,32,97,110,100,32,102,114,111,122,101,110,32,109, - 111,100,117,108,101,115,78,41,6,114,199,0,0,0,114,14, - 0,0,0,114,165,0,0,0,114,109,0,0,0,114,141,0, - 0,0,114,151,0,0,0,41,2,114,197,0,0,0,114,198, + 0,0,114,147,0,0,0,50,3,0,0,115,2,0,0,0, + 0,4,122,23,70,114,111,122,101,110,73,109,112,111,114,116, + 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,54,82,101,116, + 117,114,110,32,78,111,110,101,32,97,115,32,102,114,111,122, + 101,110,32,109,111,100,117,108,101,115,32,100,111,32,110,111, + 116,32,104,97,118,101,32,115,111,117,114,99,101,32,99,111, + 100,101,46,78,114,10,0,0,0,41,2,114,142,0,0,0, + 114,71,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,148,0,0,0,56,3,0,0,115,2,0, + 0,0,0,4,122,25,70,114,111,122,101,110,73,109,112,111, + 114,116,101,114,46,103,101,116,95,115,111,117,114,99,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 67,0,0,0,115,10,0,0,0,116,0,160,1,124,1,161, + 1,83,0,41,1,122,46,82,101,116,117,114,110,32,84,114, + 117,101,32,105,102,32,116,104,101,32,102,114,111,122,101,110, + 32,109,111,100,117,108,101,32,105,115,32,97,32,112,97,99, + 107,97,103,101,46,41,2,114,49,0,0,0,90,17,105,115, + 95,102,114,111,122,101,110,95,112,97,99,107,97,103,101,41, + 2,114,142,0,0,0,114,71,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,105,0,0,0,62, + 3,0,0,115,2,0,0,0,0,4,122,25,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,46,105,115,95,112,97, + 99,107,97,103,101,41,2,78,78,41,1,78,41,16,114,1, + 0,0,0,114,0,0,0,0,114,2,0,0,0,114,3,0, + 0,0,114,149,0,0,0,114,86,0,0,0,114,150,0,0, + 0,114,145,0,0,0,114,146,0,0,0,114,134,0,0,0, + 114,135,0,0,0,114,137,0,0,0,114,77,0,0,0,114, + 147,0,0,0,114,148,0,0,0,114,105,0,0,0,114,10, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,8,95,105,110,115,116,97,108,108,115,4,0,0, - 115,6,0,0,0,0,2,10,2,12,1,114,200,0,0,0, - 99,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, - 0,67,0,0,0,115,32,0,0,0,100,1,100,2,108,0, - 125,0,124,0,97,1,124,0,160,2,116,3,106,4,116,5, - 25,0,161,1,1,0,100,2,83,0,41,3,122,57,73,110, - 115,116,97,108,108,32,105,109,112,111,114,116,101,114,115,32, - 116,104,97,116,32,114,101,113,117,105,114,101,32,101,120,116, - 101,114,110,97,108,32,102,105,108,101,115,121,115,116,101,109, - 32,97,99,99,101,115,115,114,19,0,0,0,78,41,6,218, - 26,95,102,114,111,122,101,110,95,105,109,112,111,114,116,108, - 105,98,95,101,120,116,101,114,110,97,108,114,115,0,0,0, - 114,200,0,0,0,114,14,0,0,0,114,79,0,0,0,114, - 1,0,0,0,41,1,114,201,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,218,27,95,105,110,115, - 116,97,108,108,95,101,120,116,101,114,110,97,108,95,105,109, - 112,111,114,116,101,114,115,123,4,0,0,115,6,0,0,0, - 0,3,8,1,4,1,114,202,0,0,0,41,2,78,78,41, - 1,78,41,2,78,114,19,0,0,0,41,4,78,78,114,10, - 0,0,0,114,19,0,0,0,41,51,114,3,0,0,0,114, - 115,0,0,0,114,12,0,0,0,114,16,0,0,0,114,51, - 0,0,0,114,29,0,0,0,114,36,0,0,0,114,17,0, - 0,0,114,18,0,0,0,114,41,0,0,0,114,42,0,0, - 0,114,45,0,0,0,114,57,0,0,0,114,59,0,0,0, - 114,68,0,0,0,114,74,0,0,0,114,77,0,0,0,114, - 84,0,0,0,114,95,0,0,0,114,96,0,0,0,114,102, - 0,0,0,114,78,0,0,0,114,128,0,0,0,114,133,0, - 0,0,114,136,0,0,0,114,91,0,0,0,114,80,0,0, - 0,114,139,0,0,0,114,140,0,0,0,114,81,0,0,0, - 114,141,0,0,0,114,151,0,0,0,114,156,0,0,0,114, - 162,0,0,0,114,164,0,0,0,114,169,0,0,0,114,173, - 0,0,0,90,15,95,69,82,82,95,77,83,71,95,80,82, - 69,70,73,88,114,175,0,0,0,114,178,0,0,0,218,6, - 111,98,106,101,99,116,114,179,0,0,0,114,180,0,0,0, - 114,181,0,0,0,114,185,0,0,0,114,191,0,0,0,114, - 194,0,0,0,114,195,0,0,0,114,199,0,0,0,114,200, - 0,0,0,114,202,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,218,8,60,109, - 111,100,117,108,101,62,25,0,0,0,115,96,0,0,0,4, - 0,4,2,8,8,8,8,4,2,4,3,16,4,14,68,14, - 21,14,16,8,37,8,17,8,11,14,8,8,11,8,12,8, - 16,8,36,14,27,14,101,16,26,10,45,14,60,8,17,8, - 17,8,24,8,29,8,23,8,15,14,73,14,77,14,13,8, - 9,8,9,10,47,8,16,4,1,8,2,8,27,6,3,8, - 16,10,15,14,38,8,27,10,35,8,7,8,35,8,8, + 0,0,114,151,0,0,0,250,2,0,0,115,28,0,0,0, + 12,9,12,9,2,1,12,6,2,1,12,8,12,4,12,9, + 12,9,2,1,14,5,2,1,14,5,2,1,114,151,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,64,0,0,0,115,32,0,0,0,101,0,90,1,100, + 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, + 4,100,5,132,0,90,5,100,6,83,0,41,7,218,18,95, + 73,109,112,111,114,116,76,111,99,107,67,111,110,116,101,120, + 116,122,36,67,111,110,116,101,120,116,32,109,97,110,97,103, + 101,114,32,102,111,114,32,116,104,101,32,105,109,112,111,114, + 116,32,108,111,99,107,46,99,1,0,0,0,0,0,0,0, + 1,0,0,0,2,0,0,0,67,0,0,0,115,12,0,0, + 0,116,0,160,1,161,0,1,0,100,1,83,0,41,2,122, + 24,65,99,113,117,105,114,101,32,116,104,101,32,105,109,112, + 111,114,116,32,108,111,99,107,46,78,41,2,114,49,0,0, + 0,114,50,0,0,0,41,1,114,26,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,46,0,0, + 0,75,3,0,0,115,2,0,0,0,0,2,122,28,95,73, + 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, + 46,95,95,101,110,116,101,114,95,95,99,4,0,0,0,0, + 0,0,0,4,0,0,0,2,0,0,0,67,0,0,0,115, + 12,0,0,0,116,0,160,1,161,0,1,0,100,1,83,0, + 41,2,122,60,82,101,108,101,97,115,101,32,116,104,101,32, + 105,109,112,111,114,116,32,108,111,99,107,32,114,101,103,97, + 114,100,108,101,115,115,32,111,102,32,97,110,121,32,114,97, + 105,115,101,100,32,101,120,99,101,112,116,105,111,110,115,46, + 78,41,2,114,49,0,0,0,114,52,0,0,0,41,4,114, + 26,0,0,0,90,8,101,120,99,95,116,121,112,101,90,9, + 101,120,99,95,118,97,108,117,101,90,13,101,120,99,95,116, + 114,97,99,101,98,97,99,107,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,48,0,0,0,79,3,0,0, + 115,2,0,0,0,0,2,122,27,95,73,109,112,111,114,116, + 76,111,99,107,67,111,110,116,101,120,116,46,95,95,101,120, + 105,116,95,95,78,41,6,114,1,0,0,0,114,0,0,0, + 0,114,2,0,0,0,114,3,0,0,0,114,46,0,0,0, + 114,48,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,156,0,0,0,71,3, + 0,0,115,4,0,0,0,12,4,8,4,114,156,0,0,0, + 99,3,0,0,0,0,0,0,0,5,0,0,0,5,0,0, + 0,67,0,0,0,115,64,0,0,0,124,1,160,0,100,1, + 124,2,100,2,24,0,161,2,125,3,116,1,124,3,131,1, + 124,2,107,0,114,36,116,2,100,3,131,1,130,1,124,3, + 100,4,25,0,125,4,124,0,114,60,100,5,160,3,124,4, + 124,0,161,2,83,0,124,4,83,0,41,6,122,50,82,101, + 115,111,108,118,101,32,97,32,114,101,108,97,116,105,118,101, + 32,109,111,100,117,108,101,32,110,97,109,101,32,116,111,32, + 97,110,32,97,98,115,111,108,117,116,101,32,111,110,101,46, + 114,117,0,0,0,114,33,0,0,0,122,50,97,116,116,101, + 109,112,116,101,100,32,114,101,108,97,116,105,118,101,32,105, + 109,112,111,114,116,32,98,101,121,111,110,100,32,116,111,112, + 45,108,101,118,101,108,32,112,97,99,107,97,103,101,114,19, + 0,0,0,122,5,123,125,46,123,125,41,4,218,6,114,115, + 112,108,105,116,218,3,108,101,110,218,10,86,97,108,117,101, + 69,114,114,111,114,114,38,0,0,0,41,5,114,15,0,0, + 0,218,7,112,97,99,107,97,103,101,218,5,108,101,118,101, + 108,90,4,98,105,116,115,90,4,98,97,115,101,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,13,95,114, + 101,115,111,108,118,101,95,110,97,109,101,84,3,0,0,115, + 10,0,0,0,0,2,16,1,12,1,8,1,8,1,114,162, + 0,0,0,99,3,0,0,0,0,0,0,0,4,0,0,0, + 4,0,0,0,67,0,0,0,115,34,0,0,0,124,0,160, + 0,124,1,124,2,161,2,125,3,124,3,100,0,107,8,114, + 24,100,0,83,0,116,1,124,1,124,3,131,2,83,0,41, + 1,78,41,2,114,146,0,0,0,114,78,0,0,0,41,4, + 218,6,102,105,110,100,101,114,114,15,0,0,0,114,143,0, + 0,0,114,93,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,218,17,95,102,105,110,100,95,115,112, + 101,99,95,108,101,103,97,99,121,93,3,0,0,115,8,0, + 0,0,0,3,12,1,8,1,4,1,114,164,0,0,0,99, + 3,0,0,0,0,0,0,0,10,0,0,0,27,0,0,0, + 67,0,0,0,115,240,0,0,0,116,0,106,1,125,3,124, + 3,100,1,107,8,114,22,116,2,100,2,131,1,130,1,124, + 3,115,38,116,3,160,4,100,3,116,5,161,2,1,0,124, + 0,116,0,106,6,107,6,125,4,120,186,124,3,68,0,93, + 174,125,5,116,7,131,0,143,72,1,0,121,10,124,5,106, + 8,125,6,87,0,110,42,4,0,116,9,107,10,114,118,1, + 0,1,0,1,0,116,10,124,5,124,0,124,1,131,3,125, + 7,124,7,100,1,107,8,114,114,119,54,89,0,110,14,88, + 0,124,6,124,0,124,1,124,2,131,3,125,7,87,0,100, + 1,81,0,82,0,88,0,124,7,100,1,107,9,114,54,124, + 4,115,224,124,0,116,0,106,6,107,6,114,224,116,0,106, + 6,124,0,25,0,125,8,121,10,124,8,106,11,125,9,87, + 0,110,20,4,0,116,9,107,10,114,204,1,0,1,0,1, + 0,124,7,83,0,88,0,124,9,100,1,107,8,114,218,124, + 7,83,0,124,9,83,0,113,54,124,7,83,0,113,54,87, + 0,100,1,83,0,100,1,83,0,41,4,122,21,70,105,110, + 100,32,97,32,109,111,100,117,108,101,39,115,32,115,112,101, + 99,46,78,122,53,115,121,115,46,109,101,116,97,95,112,97, + 116,104,32,105,115,32,78,111,110,101,44,32,80,121,116,104, + 111,110,32,105,115,32,108,105,107,101,108,121,32,115,104,117, + 116,116,105,110,103,32,100,111,119,110,122,22,115,121,115,46, + 109,101,116,97,95,112,97,116,104,32,105,115,32,101,109,112, + 116,121,41,12,114,14,0,0,0,218,9,109,101,116,97,95, + 112,97,116,104,114,70,0,0,0,218,9,95,119,97,114,110, + 105,110,103,115,218,4,119,97,114,110,218,13,73,109,112,111, + 114,116,87,97,114,110,105,110,103,114,79,0,0,0,114,156, + 0,0,0,114,145,0,0,0,114,90,0,0,0,114,164,0, + 0,0,114,89,0,0,0,41,10,114,15,0,0,0,114,143, + 0,0,0,114,144,0,0,0,114,165,0,0,0,90,9,105, + 115,95,114,101,108,111,97,100,114,163,0,0,0,114,145,0, + 0,0,114,82,0,0,0,114,83,0,0,0,114,89,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,10,95,102,105,110,100,95,115,112,101,99,102,3,0,0, + 115,54,0,0,0,0,2,6,1,8,2,8,3,4,1,12, + 5,10,1,10,1,8,1,2,1,10,1,14,1,12,1,8, + 1,8,2,22,1,8,2,14,1,10,1,2,1,10,1,14, + 4,6,2,8,1,4,2,6,2,8,2,114,169,0,0,0, + 99,3,0,0,0,0,0,0,0,3,0,0,0,5,0,0, + 0,67,0,0,0,115,108,0,0,0,116,0,124,0,116,1, + 131,2,115,28,116,2,100,1,160,3,116,4,124,0,131,1, + 161,1,131,1,130,1,124,2,100,2,107,0,114,44,116,5, + 100,3,131,1,130,1,124,2,100,2,107,4,114,84,116,0, + 124,1,116,1,131,2,115,72,116,2,100,4,131,1,130,1, + 110,12,124,1,115,84,116,6,100,5,131,1,130,1,124,0, + 115,104,124,2,100,2,107,2,114,104,116,5,100,6,131,1, + 130,1,100,7,83,0,41,8,122,28,86,101,114,105,102,121, + 32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,34, + 115,97,110,101,34,46,122,31,109,111,100,117,108,101,32,110, + 97,109,101,32,109,117,115,116,32,98,101,32,115,116,114,44, + 32,110,111,116,32,123,125,114,19,0,0,0,122,18,108,101, + 118,101,108,32,109,117,115,116,32,98,101,32,62,61,32,48, + 122,31,95,95,112,97,99,107,97,103,101,95,95,32,110,111, + 116,32,115,101,116,32,116,111,32,97,32,115,116,114,105,110, + 103,122,54,97,116,116,101,109,112,116,101,100,32,114,101,108, + 97,116,105,118,101,32,105,109,112,111,114,116,32,119,105,116, + 104,32,110,111,32,107,110,111,119,110,32,112,97,114,101,110, + 116,32,112,97,99,107,97,103,101,122,17,69,109,112,116,121, + 32,109,111,100,117,108,101,32,110,97,109,101,78,41,7,218, + 10,105,115,105,110,115,116,97,110,99,101,218,3,115,116,114, + 218,9,84,121,112,101,69,114,114,111,114,114,38,0,0,0, + 114,13,0,0,0,114,159,0,0,0,114,70,0,0,0,41, + 3,114,15,0,0,0,114,160,0,0,0,114,161,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, + 13,95,115,97,110,105,116,121,95,99,104,101,99,107,149,3, + 0,0,115,22,0,0,0,0,2,10,1,18,1,8,1,8, + 1,8,1,10,1,10,1,4,1,8,2,12,1,114,173,0, + 0,0,122,16,78,111,32,109,111,100,117,108,101,32,110,97, + 109,101,100,32,122,4,123,33,114,125,99,2,0,0,0,0, + 0,0,0,8,0,0,0,13,0,0,0,67,0,0,0,115, + 220,0,0,0,100,0,125,2,124,0,160,0,100,1,161,1, + 100,2,25,0,125,3,124,3,114,134,124,3,116,1,106,2, + 107,7,114,42,116,3,124,1,124,3,131,2,1,0,124,0, + 116,1,106,2,107,6,114,62,116,1,106,2,124,0,25,0, + 83,0,116,1,106,2,124,3,25,0,125,4,121,10,124,4, + 106,4,125,2,87,0,110,50,4,0,116,5,107,10,114,132, + 1,0,1,0,1,0,116,6,100,3,23,0,160,7,124,0, + 124,3,161,2,125,5,116,8,124,5,124,0,100,4,141,2, + 100,0,130,2,89,0,110,2,88,0,116,9,124,0,124,2, + 131,2,125,6,124,6,100,0,107,8,114,172,116,8,116,6, + 160,7,124,0,161,1,124,0,100,4,141,2,130,1,110,8, + 116,10,124,6,131,1,125,7,124,3,114,216,116,1,106,2, + 124,3,25,0,125,4,116,11,124,4,124,0,160,0,100,1, + 161,1,100,5,25,0,124,7,131,3,1,0,124,7,83,0, + 41,6,78,114,117,0,0,0,114,19,0,0,0,122,23,59, + 32,123,33,114,125,32,105,115,32,110,111,116,32,97,32,112, + 97,99,107,97,103,101,41,1,114,15,0,0,0,233,2,0, + 0,0,41,12,114,118,0,0,0,114,14,0,0,0,114,79, + 0,0,0,114,59,0,0,0,114,127,0,0,0,114,90,0, + 0,0,218,8,95,69,82,82,95,77,83,71,114,38,0,0, + 0,218,19,77,111,100,117,108,101,78,111,116,70,111,117,110, + 100,69,114,114,111,114,114,169,0,0,0,114,140,0,0,0, + 114,5,0,0,0,41,8,114,15,0,0,0,218,7,105,109, + 112,111,114,116,95,114,143,0,0,0,114,119,0,0,0,90, + 13,112,97,114,101,110,116,95,109,111,100,117,108,101,114,138, + 0,0,0,114,82,0,0,0,114,83,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,23,95,102, + 105,110,100,95,97,110,100,95,108,111,97,100,95,117,110,108, + 111,99,107,101,100,168,3,0,0,115,42,0,0,0,0,1, + 4,1,14,1,4,1,10,1,10,2,10,1,10,1,10,1, + 2,1,10,1,14,1,16,1,20,1,10,1,8,1,20,2, + 8,1,4,2,10,1,22,1,114,178,0,0,0,99,2,0, + 0,0,0,0,0,0,4,0,0,0,11,0,0,0,67,0, + 0,0,115,94,0,0,0,116,0,124,0,131,1,143,38,1, + 0,116,1,106,2,160,3,124,0,116,4,161,2,125,2,124, + 2,116,4,107,8,114,42,116,5,124,0,124,1,131,2,83, + 0,87,0,100,1,81,0,82,0,88,0,124,2,100,1,107, + 8,114,82,100,2,160,6,124,0,161,1,125,3,116,7,124, + 3,124,0,100,3,141,2,130,1,116,8,124,0,131,1,1, + 0,124,2,83,0,41,4,122,25,70,105,110,100,32,97,110, + 100,32,108,111,97,100,32,116,104,101,32,109,111,100,117,108, + 101,46,78,122,40,105,109,112,111,114,116,32,111,102,32,123, + 125,32,104,97,108,116,101,100,59,32,78,111,110,101,32,105, + 110,32,115,121,115,46,109,111,100,117,108,101,115,41,1,114, + 15,0,0,0,41,9,114,42,0,0,0,114,14,0,0,0, + 114,79,0,0,0,114,30,0,0,0,218,14,95,78,69,69, + 68,83,95,76,79,65,68,73,78,71,114,178,0,0,0,114, + 38,0,0,0,114,176,0,0,0,114,57,0,0,0,41,4, + 114,15,0,0,0,114,177,0,0,0,114,83,0,0,0,114, + 67,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,14,95,102,105,110,100,95,97,110,100,95,108, + 111,97,100,198,3,0,0,115,20,0,0,0,0,2,10,1, + 14,1,8,1,20,2,8,1,4,1,6,1,12,2,8,1, + 114,180,0,0,0,114,19,0,0,0,99,3,0,0,0,0, + 0,0,0,3,0,0,0,4,0,0,0,67,0,0,0,115, + 42,0,0,0,116,0,124,0,124,1,124,2,131,3,1,0, + 124,2,100,1,107,4,114,32,116,1,124,0,124,1,124,2, + 131,3,125,0,116,2,124,0,116,3,131,2,83,0,41,2, + 97,50,1,0,0,73,109,112,111,114,116,32,97,110,100,32, + 114,101,116,117,114,110,32,116,104,101,32,109,111,100,117,108, + 101,32,98,97,115,101,100,32,111,110,32,105,116,115,32,110, + 97,109,101,44,32,116,104,101,32,112,97,99,107,97,103,101, + 32,116,104,101,32,99,97,108,108,32,105,115,10,32,32,32, + 32,98,101,105,110,103,32,109,97,100,101,32,102,114,111,109, + 44,32,97,110,100,32,116,104,101,32,108,101,118,101,108,32, + 97,100,106,117,115,116,109,101,110,116,46,10,10,32,32,32, + 32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,114, + 101,112,114,101,115,101,110,116,115,32,116,104,101,32,103,114, + 101,97,116,101,115,116,32,99,111,109,109,111,110,32,100,101, + 110,111,109,105,110,97,116,111,114,32,111,102,32,102,117,110, + 99,116,105,111,110,97,108,105,116,121,10,32,32,32,32,98, + 101,116,119,101,101,110,32,105,109,112,111,114,116,95,109,111, + 100,117,108,101,32,97,110,100,32,95,95,105,109,112,111,114, + 116,95,95,46,32,84,104,105,115,32,105,110,99,108,117,100, + 101,115,32,115,101,116,116,105,110,103,32,95,95,112,97,99, + 107,97,103,101,95,95,32,105,102,10,32,32,32,32,116,104, + 101,32,108,111,97,100,101,114,32,100,105,100,32,110,111,116, + 46,10,10,32,32,32,32,114,19,0,0,0,41,4,114,173, + 0,0,0,114,162,0,0,0,114,180,0,0,0,218,11,95, + 103,99,100,95,105,109,112,111,114,116,41,3,114,15,0,0, + 0,114,160,0,0,0,114,161,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,181,0,0,0,214, + 3,0,0,115,8,0,0,0,0,9,12,1,8,1,12,1, + 114,181,0,0,0,41,1,218,9,114,101,99,117,114,115,105, + 118,101,99,3,0,0,0,1,0,0,0,8,0,0,0,17, + 0,0,0,67,0,0,0,115,234,0,0,0,116,0,124,0, + 100,1,131,2,114,230,120,218,124,1,68,0,93,210,125,4, + 116,1,124,4,116,2,131,2,115,78,124,3,114,46,124,0, + 106,3,100,2,23,0,125,5,110,4,100,3,125,5,116,4, + 100,4,124,5,155,0,100,5,116,5,124,4,131,1,106,3, + 155,0,157,4,131,1,130,1,113,16,124,4,100,6,107,2, + 114,120,124,3,115,226,116,0,124,0,100,7,131,2,114,226, + 116,6,124,0,124,0,106,7,124,2,100,8,100,9,141,4, + 1,0,113,16,116,0,124,0,124,4,131,2,115,16,100,10, + 160,8,124,0,106,3,124,4,161,2,125,6,121,14,116,9, + 124,2,124,6,131,2,1,0,87,0,113,16,4,0,116,10, + 107,10,114,224,1,0,125,7,1,0,122,38,124,7,106,11, + 124,6,107,2,114,206,116,12,106,13,160,14,124,6,116,15, + 161,2,100,11,107,9,114,206,119,16,130,0,87,0,89,0, + 100,11,100,11,125,7,126,7,88,0,113,16,88,0,113,16, + 87,0,124,0,83,0,41,12,122,238,70,105,103,117,114,101, + 32,111,117,116,32,119,104,97,116,32,95,95,105,109,112,111, + 114,116,95,95,32,115,104,111,117,108,100,32,114,101,116,117, + 114,110,46,10,10,32,32,32,32,84,104,101,32,105,109,112, + 111,114,116,95,32,112,97,114,97,109,101,116,101,114,32,105, + 115,32,97,32,99,97,108,108,97,98,108,101,32,119,104,105, + 99,104,32,116,97,107,101,115,32,116,104,101,32,110,97,109, + 101,32,111,102,32,109,111,100,117,108,101,32,116,111,10,32, + 32,32,32,105,109,112,111,114,116,46,32,73,116,32,105,115, + 32,114,101,113,117,105,114,101,100,32,116,111,32,100,101,99, + 111,117,112,108,101,32,116,104,101,32,102,117,110,99,116,105, + 111,110,32,102,114,111,109,32,97,115,115,117,109,105,110,103, + 32,105,109,112,111,114,116,108,105,98,39,115,10,32,32,32, + 32,105,109,112,111,114,116,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,105,115,32,100,101,115,105,114,101, + 100,46,10,10,32,32,32,32,114,127,0,0,0,122,8,46, + 95,95,97,108,108,95,95,122,13,96,96,102,114,111,109,32, + 108,105,115,116,39,39,122,8,73,116,101,109,32,105,110,32, + 122,18,32,109,117,115,116,32,98,101,32,115,116,114,44,32, + 110,111,116,32,250,1,42,218,7,95,95,97,108,108,95,95, + 84,41,1,114,182,0,0,0,122,5,123,125,46,123,125,78, + 41,16,114,4,0,0,0,114,170,0,0,0,114,171,0,0, + 0,114,1,0,0,0,114,172,0,0,0,114,13,0,0,0, + 218,16,95,104,97,110,100,108,101,95,102,114,111,109,108,105, + 115,116,114,184,0,0,0,114,38,0,0,0,114,59,0,0, + 0,114,176,0,0,0,114,15,0,0,0,114,14,0,0,0, + 114,79,0,0,0,114,30,0,0,0,114,179,0,0,0,41, + 8,114,83,0,0,0,218,8,102,114,111,109,108,105,115,116, + 114,177,0,0,0,114,182,0,0,0,218,1,120,90,5,119, + 104,101,114,101,90,9,102,114,111,109,95,110,97,109,101,90, + 3,101,120,99,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,185,0,0,0,229,3,0,0,115,42,0,0, + 0,0,10,10,1,10,1,10,1,4,1,12,2,4,1,28, + 2,8,1,14,1,10,1,10,1,10,1,14,1,2,1,14, + 1,16,4,10,1,18,1,2,1,24,1,114,185,0,0,0, + 99,1,0,0,0,0,0,0,0,3,0,0,0,6,0,0, + 0,67,0,0,0,115,146,0,0,0,124,0,160,0,100,1, + 161,1,125,1,124,0,160,0,100,2,161,1,125,2,124,1, + 100,3,107,9,114,82,124,2,100,3,107,9,114,78,124,1, + 124,2,106,1,107,3,114,78,116,2,106,3,100,4,124,1, + 155,2,100,5,124,2,106,1,155,2,100,6,157,5,116,4, + 100,7,100,8,141,3,1,0,124,1,83,0,124,2,100,3, + 107,9,114,96,124,2,106,1,83,0,116,2,106,3,100,9, + 116,4,100,7,100,8,141,3,1,0,124,0,100,10,25,0, + 125,1,100,11,124,0,107,7,114,142,124,1,160,5,100,12, + 161,1,100,13,25,0,125,1,124,1,83,0,41,14,122,167, + 67,97,108,99,117,108,97,116,101,32,119,104,97,116,32,95, + 95,112,97,99,107,97,103,101,95,95,32,115,104,111,117,108, + 100,32,98,101,46,10,10,32,32,32,32,95,95,112,97,99, + 107,97,103,101,95,95,32,105,115,32,110,111,116,32,103,117, + 97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100, + 101,102,105,110,101,100,32,111,114,32,99,111,117,108,100,32, + 98,101,32,115,101,116,32,116,111,32,78,111,110,101,10,32, + 32,32,32,116,111,32,114,101,112,114,101,115,101,110,116,32, + 116,104,97,116,32,105,116,115,32,112,114,111,112,101,114,32, + 118,97,108,117,101,32,105,115,32,117,110,107,110,111,119,110, + 46,10,10,32,32,32,32,114,130,0,0,0,114,89,0,0, + 0,78,122,32,95,95,112,97,99,107,97,103,101,95,95,32, + 33,61,32,95,95,115,112,101,99,95,95,46,112,97,114,101, + 110,116,32,40,122,4,32,33,61,32,250,1,41,233,3,0, + 0,0,41,1,90,10,115,116,97,99,107,108,101,118,101,108, + 122,89,99,97,110,39,116,32,114,101,115,111,108,118,101,32, + 112,97,99,107,97,103,101,32,102,114,111,109,32,95,95,115, + 112,101,99,95,95,32,111,114,32,95,95,112,97,99,107,97, + 103,101,95,95,44,32,102,97,108,108,105,110,103,32,98,97, + 99,107,32,111,110,32,95,95,110,97,109,101,95,95,32,97, + 110,100,32,95,95,112,97,116,104,95,95,114,1,0,0,0, + 114,127,0,0,0,114,117,0,0,0,114,19,0,0,0,41, + 6,114,30,0,0,0,114,119,0,0,0,114,166,0,0,0, + 114,167,0,0,0,114,168,0,0,0,114,118,0,0,0,41, + 3,218,7,103,108,111,98,97,108,115,114,160,0,0,0,114, + 82,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,17,95,99,97,108,99,95,95,95,112,97,99, + 107,97,103,101,95,95,11,4,0,0,115,30,0,0,0,0, + 7,10,1,10,1,8,1,18,1,22,2,10,1,4,1,8, + 1,6,2,6,2,10,1,8,1,8,1,14,1,114,191,0, + 0,0,114,10,0,0,0,99,5,0,0,0,0,0,0,0, + 9,0,0,0,5,0,0,0,67,0,0,0,115,166,0,0, + 0,124,4,100,1,107,2,114,18,116,0,124,0,131,1,125, + 5,110,36,124,1,100,2,107,9,114,30,124,1,110,2,105, + 0,125,6,116,1,124,6,131,1,125,7,116,0,124,0,124, + 7,124,4,131,3,125,5,124,3,115,150,124,4,100,1,107, + 2,114,84,116,0,124,0,160,2,100,3,161,1,100,1,25, + 0,131,1,83,0,124,0,115,92,124,5,83,0,116,3,124, + 0,131,1,116,3,124,0,160,2,100,3,161,1,100,1,25, + 0,131,1,24,0,125,8,116,4,106,5,124,5,106,6,100, + 2,116,3,124,5,106,6,131,1,124,8,24,0,133,2,25, + 0,25,0,83,0,110,12,116,7,124,5,124,3,116,0,131, + 3,83,0,100,2,83,0,41,4,97,215,1,0,0,73,109, + 112,111,114,116,32,97,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,84,104,101,32,39,103,108,111,98,97,108,115, + 39,32,97,114,103,117,109,101,110,116,32,105,115,32,117,115, + 101,100,32,116,111,32,105,110,102,101,114,32,119,104,101,114, + 101,32,116,104,101,32,105,109,112,111,114,116,32,105,115,32, + 111,99,99,117,114,114,105,110,103,32,102,114,111,109,10,32, + 32,32,32,116,111,32,104,97,110,100,108,101,32,114,101,108, + 97,116,105,118,101,32,105,109,112,111,114,116,115,46,32,84, + 104,101,32,39,108,111,99,97,108,115,39,32,97,114,103,117, + 109,101,110,116,32,105,115,32,105,103,110,111,114,101,100,46, + 32,84,104,101,10,32,32,32,32,39,102,114,111,109,108,105, + 115,116,39,32,97,114,103,117,109,101,110,116,32,115,112,101, + 99,105,102,105,101,115,32,119,104,97,116,32,115,104,111,117, + 108,100,32,101,120,105,115,116,32,97,115,32,97,116,116,114, + 105,98,117,116,101,115,32,111,110,32,116,104,101,32,109,111, + 100,117,108,101,10,32,32,32,32,98,101,105,110,103,32,105, + 109,112,111,114,116,101,100,32,40,101,46,103,46,32,96,96, + 102,114,111,109,32,109,111,100,117,108,101,32,105,109,112,111, + 114,116,32,60,102,114,111,109,108,105,115,116,62,96,96,41, + 46,32,32,84,104,101,32,39,108,101,118,101,108,39,10,32, + 32,32,32,97,114,103,117,109,101,110,116,32,114,101,112,114, + 101,115,101,110,116,115,32,116,104,101,32,112,97,99,107,97, + 103,101,32,108,111,99,97,116,105,111,110,32,116,111,32,105, + 109,112,111,114,116,32,102,114,111,109,32,105,110,32,97,32, + 114,101,108,97,116,105,118,101,10,32,32,32,32,105,109,112, + 111,114,116,32,40,101,46,103,46,32,96,96,102,114,111,109, + 32,46,46,112,107,103,32,105,109,112,111,114,116,32,109,111, + 100,96,96,32,119,111,117,108,100,32,104,97,118,101,32,97, + 32,39,108,101,118,101,108,39,32,111,102,32,50,41,46,10, + 10,32,32,32,32,114,19,0,0,0,78,114,117,0,0,0, + 41,8,114,181,0,0,0,114,191,0,0,0,218,9,112,97, + 114,116,105,116,105,111,110,114,158,0,0,0,114,14,0,0, + 0,114,79,0,0,0,114,1,0,0,0,114,185,0,0,0, + 41,9,114,15,0,0,0,114,190,0,0,0,218,6,108,111, + 99,97,108,115,114,186,0,0,0,114,161,0,0,0,114,83, + 0,0,0,90,8,103,108,111,98,97,108,115,95,114,160,0, + 0,0,90,7,99,117,116,95,111,102,102,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,218,10,95,95,105,109, + 112,111,114,116,95,95,38,4,0,0,115,26,0,0,0,0, + 11,8,1,10,2,16,1,8,1,12,1,4,3,8,1,18, + 1,4,1,4,4,26,3,32,2,114,194,0,0,0,99,1, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,38,0,0,0,116,0,160,1,124,0,161,1, + 125,1,124,1,100,0,107,8,114,30,116,2,100,1,124,0, + 23,0,131,1,130,1,116,3,124,1,131,1,83,0,41,2, + 78,122,25,110,111,32,98,117,105,108,116,45,105,110,32,109, + 111,100,117,108,101,32,110,97,109,101,100,32,41,4,114,141, + 0,0,0,114,145,0,0,0,114,70,0,0,0,114,140,0, + 0,0,41,2,114,15,0,0,0,114,82,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,218,18,95, + 98,117,105,108,116,105,110,95,102,114,111,109,95,110,97,109, + 101,73,4,0,0,115,8,0,0,0,0,1,10,1,8,1, + 12,1,114,195,0,0,0,99,2,0,0,0,0,0,0,0, + 10,0,0,0,5,0,0,0,67,0,0,0,115,174,0,0, + 0,124,1,97,0,124,0,97,1,116,2,116,1,131,1,125, + 2,120,86,116,1,106,3,160,4,161,0,68,0,93,72,92, + 2,125,3,125,4,116,5,124,4,124,2,131,2,114,28,124, + 3,116,1,106,6,107,6,114,62,116,7,125,5,110,18,116, + 0,160,8,124,3,161,1,114,28,116,9,125,5,110,2,113, + 28,116,10,124,4,124,5,131,2,125,6,116,11,124,6,124, + 4,131,2,1,0,113,28,87,0,116,1,106,3,116,12,25, + 0,125,7,120,54,100,1,68,0,93,46,125,8,124,8,116, + 1,106,3,107,7,114,144,116,13,124,8,131,1,125,9,110, + 10,116,1,106,3,124,8,25,0,125,9,116,14,124,7,124, + 8,124,9,131,3,1,0,113,120,87,0,100,2,83,0,41, + 3,122,250,83,101,116,117,112,32,105,109,112,111,114,116,108, + 105,98,32,98,121,32,105,109,112,111,114,116,105,110,103,32, + 110,101,101,100,101,100,32,98,117,105,108,116,45,105,110,32, + 109,111,100,117,108,101,115,32,97,110,100,32,105,110,106,101, + 99,116,105,110,103,32,116,104,101,109,10,32,32,32,32,105, + 110,116,111,32,116,104,101,32,103,108,111,98,97,108,32,110, + 97,109,101,115,112,97,99,101,46,10,10,32,32,32,32,65, + 115,32,115,121,115,32,105,115,32,110,101,101,100,101,100,32, + 102,111,114,32,115,121,115,46,109,111,100,117,108,101,115,32, + 97,99,99,101,115,115,32,97,110,100,32,95,105,109,112,32, + 105,115,32,110,101,101,100,101,100,32,116,111,32,108,111,97, + 100,32,98,117,105,108,116,45,105,110,10,32,32,32,32,109, + 111,100,117,108,101,115,44,32,116,104,111,115,101,32,116,119, + 111,32,109,111,100,117,108,101,115,32,109,117,115,116,32,98, + 101,32,101,120,112,108,105,99,105,116,108,121,32,112,97,115, + 115,101,100,32,105,110,46,10,10,32,32,32,32,41,3,114, + 20,0,0,0,114,166,0,0,0,114,56,0,0,0,78,41, + 15,114,49,0,0,0,114,14,0,0,0,114,13,0,0,0, + 114,79,0,0,0,218,5,105,116,101,109,115,114,170,0,0, + 0,114,69,0,0,0,114,141,0,0,0,114,75,0,0,0, + 114,151,0,0,0,114,128,0,0,0,114,133,0,0,0,114, + 1,0,0,0,114,195,0,0,0,114,5,0,0,0,41,10, + 218,10,115,121,115,95,109,111,100,117,108,101,218,11,95,105, + 109,112,95,109,111,100,117,108,101,90,11,109,111,100,117,108, + 101,95,116,121,112,101,114,15,0,0,0,114,83,0,0,0, + 114,93,0,0,0,114,82,0,0,0,90,11,115,101,108,102, + 95,109,111,100,117,108,101,90,12,98,117,105,108,116,105,110, + 95,110,97,109,101,90,14,98,117,105,108,116,105,110,95,109, + 111,100,117,108,101,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,6,95,115,101,116,117,112,80,4,0,0, + 115,36,0,0,0,0,9,4,1,4,3,8,1,20,1,10, + 1,10,1,6,1,10,1,6,2,2,1,10,1,14,3,10, + 1,10,1,10,1,10,2,10,1,114,199,0,0,0,99,2, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,38,0,0,0,116,0,124,0,124,1,131,2, + 1,0,116,1,106,2,160,3,116,4,161,1,1,0,116,1, + 106,2,160,3,116,5,161,1,1,0,100,1,83,0,41,2, + 122,48,73,110,115,116,97,108,108,32,105,109,112,111,114,116, + 101,114,115,32,102,111,114,32,98,117,105,108,116,105,110,32, + 97,110,100,32,102,114,111,122,101,110,32,109,111,100,117,108, + 101,115,78,41,6,114,199,0,0,0,114,14,0,0,0,114, + 165,0,0,0,114,109,0,0,0,114,141,0,0,0,114,151, + 0,0,0,41,2,114,197,0,0,0,114,198,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,8, + 95,105,110,115,116,97,108,108,115,4,0,0,115,6,0,0, + 0,0,2,10,2,12,1,114,200,0,0,0,99,0,0,0, + 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, + 0,115,32,0,0,0,100,1,100,2,108,0,125,0,124,0, + 97,1,124,0,160,2,116,3,106,4,116,5,25,0,161,1, + 1,0,100,2,83,0,41,3,122,57,73,110,115,116,97,108, + 108,32,105,109,112,111,114,116,101,114,115,32,116,104,97,116, + 32,114,101,113,117,105,114,101,32,101,120,116,101,114,110,97, + 108,32,102,105,108,101,115,121,115,116,101,109,32,97,99,99, + 101,115,115,114,19,0,0,0,78,41,6,218,26,95,102,114, + 111,122,101,110,95,105,109,112,111,114,116,108,105,98,95,101, + 120,116,101,114,110,97,108,114,115,0,0,0,114,200,0,0, + 0,114,14,0,0,0,114,79,0,0,0,114,1,0,0,0, + 41,1,114,201,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,218,27,95,105,110,115,116,97,108,108, + 95,101,120,116,101,114,110,97,108,95,105,109,112,111,114,116, + 101,114,115,123,4,0,0,115,6,0,0,0,0,3,8,1, + 4,1,114,202,0,0,0,41,2,78,78,41,1,78,41,2, + 78,114,19,0,0,0,41,4,78,78,114,10,0,0,0,114, + 19,0,0,0,41,51,114,3,0,0,0,114,115,0,0,0, + 114,12,0,0,0,114,16,0,0,0,114,51,0,0,0,114, + 29,0,0,0,114,36,0,0,0,114,17,0,0,0,114,18, + 0,0,0,114,41,0,0,0,114,42,0,0,0,114,45,0, + 0,0,114,57,0,0,0,114,59,0,0,0,114,68,0,0, + 0,114,74,0,0,0,114,77,0,0,0,114,84,0,0,0, + 114,95,0,0,0,114,96,0,0,0,114,102,0,0,0,114, + 78,0,0,0,114,128,0,0,0,114,133,0,0,0,114,136, + 0,0,0,114,91,0,0,0,114,80,0,0,0,114,139,0, + 0,0,114,140,0,0,0,114,81,0,0,0,114,141,0,0, + 0,114,151,0,0,0,114,156,0,0,0,114,162,0,0,0, + 114,164,0,0,0,114,169,0,0,0,114,173,0,0,0,90, + 15,95,69,82,82,95,77,83,71,95,80,82,69,70,73,88, + 114,175,0,0,0,114,178,0,0,0,218,6,111,98,106,101, + 99,116,114,179,0,0,0,114,180,0,0,0,114,181,0,0, + 0,114,185,0,0,0,114,191,0,0,0,114,194,0,0,0, + 114,195,0,0,0,114,199,0,0,0,114,200,0,0,0,114, + 202,0,0,0,114,10,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,218,8,60,109,111,100,117,108, + 101,62,25,0,0,0,115,96,0,0,0,4,0,4,2,8, + 8,8,8,4,2,4,3,16,4,14,68,14,21,14,16,8, + 37,8,17,8,11,14,8,8,11,8,12,8,16,8,36,14, + 27,14,101,16,26,10,45,14,60,8,17,8,17,8,24,8, + 29,8,23,8,15,14,73,14,77,14,13,8,9,8,9,10, + 47,8,16,4,1,8,2,8,27,6,3,8,16,10,15,14, + 38,8,27,10,35,8,7,8,35,8,8, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 6b900731c51..ea6f75aa43a 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -527,200 +527,151 @@ const unsigned char _Py_M__importlib_external[] = { 101,46,60,108,111,99,97,108,115,62,46,95,99,104,101,99, 107,95,110,97,109,101,95,119,114,97,112,112,101,114,99,2, 0,0,0,0,0,0,0,3,0,0,0,7,0,0,0,83, - 0,0,0,115,60,0,0,0,120,40,100,5,68,0,93,32, + 0,0,0,115,60,0,0,0,120,40,100,1,68,0,93,32, 125,2,116,0,124,1,124,2,131,2,114,6,116,1,124,0, 124,2,116,2,124,1,124,2,131,2,131,3,1,0,113,6, 87,0,124,0,106,3,160,4,124,1,106,3,161,1,1,0, - 100,0,83,0,41,6,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,4,114,106,0,0,0,114,107,0,0,0, - 114,108,0,0,0,114,109,0,0,0,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,53,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,218,5,95,119,114,97,112, - 151,1,0,0,115,8,0,0,0,0,1,10,1,10,1,22, - 1,122,26,95,99,104,101,99,107,95,110,97,109,101,46,60, - 108,111,99,97,108,115,62,46,95,119,114,97,112,41,1,78, - 41,3,218,10,95,98,111,111,116,115,116,114,97,112,114,115, - 0,0,0,218,9,78,97,109,101,69,114,114,111,114,41,3, - 114,104,0,0,0,114,105,0,0,0,114,115,0,0,0,114, - 2,0,0,0,41,1,114,104,0,0,0,114,4,0,0,0, - 218,11,95,99,104,101,99,107,95,110,97,109,101,132,1,0, - 0,115,14,0,0,0,0,8,14,7,2,1,10,1,14,2, - 14,5,10,1,114,118,0,0,0,99,2,0,0,0,0,0, - 0,0,5,0,0,0,6,0,0,0,67,0,0,0,115,60, - 0,0,0,124,0,160,0,124,1,161,1,92,2,125,2,125, - 3,124,2,100,1,107,8,114,56,116,1,124,3,131,1,114, - 56,100,2,125,4,116,2,160,3,124,4,160,4,124,3,100, - 3,25,0,161,1,116,5,161,2,1,0,124,2,83,0,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,60,0, - 0,0,41,6,218,11,102,105,110,100,95,108,111,97,100,101, - 114,114,31,0,0,0,114,61,0,0,0,114,62,0,0,0, - 114,48,0,0,0,218,13,73,109,112,111,114,116,87,97,114, - 110,105,110,103,41,5,114,102,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,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,218,17,95,102,105, - 110,100,95,109,111,100,117,108,101,95,115,104,105,109,160,1, - 0,0,115,10,0,0,0,0,10,14,1,16,1,4,1,22, - 1,114,125,0,0,0,99,3,0,0,0,0,0,0,0,6, - 0,0,0,4,0,0,0,67,0,0,0,115,158,0,0,0, - 124,0,100,1,100,2,133,2,25,0,125,3,124,3,116,0, - 107,3,114,60,100,3,124,1,155,2,100,4,124,3,155,2, - 157,4,125,4,116,1,160,2,100,5,124,4,161,2,1,0, - 116,3,124,4,102,1,124,2,142,1,130,1,116,4,124,0, - 131,1,100,6,107,0,114,102,100,7,124,1,155,2,157,2, - 125,4,116,1,160,2,100,5,124,4,161,2,1,0,116,5, - 124,4,131,1,130,1,116,6,124,0,100,2,100,8,133,2, - 25,0,131,1,125,5,124,5,100,9,64,0,114,154,100,10, - 124,5,155,2,100,11,124,1,155,2,157,4,125,4,116,3, - 124,4,102,1,124,2,142,1,130,1,124,5,83,0,41,12, - 97,84,2,0,0,80,101,114,102,111,114,109,32,98,97,115, - 105,99,32,118,97,108,105,100,105,116,121,32,99,104,101,99, - 107,105,110,103,32,111,102,32,97,32,112,121,99,32,104,101, - 97,100,101,114,32,97,110,100,32,114,101,116,117,114,110,32, - 116,104,101,32,102,108,97,103,115,32,102,105,101,108,100,44, - 10,32,32,32,32,119,104,105,99,104,32,100,101,116,101,114, - 109,105,110,101,115,32,104,111,119,32,116,104,101,32,112,121, - 99,32,115,104,111,117,108,100,32,98,101,32,102,117,114,116, - 104,101,114,32,118,97,108,105,100,97,116,101,100,32,97,103, - 97,105,110,115,116,32,116,104,101,32,115,111,117,114,99,101, - 46,10,10,32,32,32,32,42,100,97,116,97,42,32,105,115, - 32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102, - 32,116,104,101,32,112,121,99,32,102,105,108,101,46,32,40, - 79,110,108,121,32,116,104,101,32,102,105,114,115,116,32,49, - 54,32,98,121,116,101,115,32,97,114,101,10,32,32,32,32, - 114,101,113,117,105,114,101,100,44,32,116,104,111,117,103,104, - 46,41,10,10,32,32,32,32,42,110,97,109,101,42,32,105, - 115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104, - 101,32,109,111,100,117,108,101,32,98,101,105,110,103,32,105, - 109,112,111,114,116,101,100,46,32,73,116,32,105,115,32,117, - 115,101,100,32,102,111,114,32,108,111,103,103,105,110,103,46, - 10,10,32,32,32,32,42,101,120,99,95,100,101,116,97,105, - 108,115,42,32,105,115,32,97,32,100,105,99,116,105,111,110, - 97,114,121,32,112,97,115,115,101,100,32,116,111,32,73,109, - 112,111,114,116,69,114,114,111,114,32,105,102,32,105,116,32, - 114,97,105,115,101,100,32,102,111,114,10,32,32,32,32,105, - 109,112,114,111,118,101,100,32,100,101,98,117,103,103,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,119,104,101,110,32,116,104,101,32,102,108,97, - 103,115,10,32,32,32,32,102,105,101,108,100,32,105,115,32, - 105,110,118,97,108,105,100,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,32,116,114,117,110,99,97,116, - 101,100,46,10,10,32,32,32,32,78,114,12,0,0,0,122, - 20,98,97,100,32,109,97,103,105,99,32,110,117,109,98,101, - 114,32,105,110,32,122,2,58,32,122,2,123,125,233,16,0, - 0,0,122,40,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,112,121, - 99,32,104,101,97,100,101,114,32,111,102,32,233,8,0,0, - 0,233,252,255,255,255,122,14,105,110,118,97,108,105,100,32, - 102,108,97,103,115,32,122,4,32,105,110,32,41,7,218,12, - 77,65,71,73,67,95,78,85,77,66,69,82,114,116,0,0, - 0,218,16,95,118,101,114,98,111,115,101,95,109,101,115,115, - 97,103,101,114,101,0,0,0,114,31,0,0,0,218,8,69, - 79,70,69,114,114,111,114,114,19,0,0,0,41,6,114,54, - 0,0,0,114,100,0,0,0,218,11,101,120,99,95,100,101, - 116,97,105,108,115,90,5,109,97,103,105,99,114,77,0,0, - 0,114,69,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,13,95,99,108,97,115,115,105,102,121, - 95,112,121,99,177,1,0,0,115,28,0,0,0,0,16,12, - 1,8,1,16,1,12,1,12,1,12,1,10,1,12,1,8, - 1,16,2,8,1,16,1,12,1,114,133,0,0,0,99,5, - 0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,67, - 0,0,0,115,112,0,0,0,116,0,124,0,100,1,100,2, - 133,2,25,0,131,1,124,1,100,3,64,0,107,3,114,58, - 100,4,124,3,155,2,157,2,125,5,116,1,160,2,100,5, - 124,5,161,2,1,0,116,3,124,5,102,1,124,4,142,1, - 130,1,124,2,100,6,107,9,114,108,116,0,124,0,100,2, - 100,7,133,2,25,0,131,1,124,2,100,3,64,0,107,3, - 114,108,116,3,100,4,124,3,155,2,157,2,102,1,124,4, - 142,1,130,1,100,6,83,0,41,8,97,7,2,0,0,86, - 97,108,105,100,97,116,101,32,97,32,112,121,99,32,97,103, - 97,105,110,115,116,32,116,104,101,32,115,111,117,114,99,101, - 32,108,97,115,116,45,109,111,100,105,102,105,101,100,32,116, - 105,109,101,46,10,10,32,32,32,32,42,100,97,116,97,42, - 32,105,115,32,116,104,101,32,99,111,110,116,101,110,116,115, - 32,111,102,32,116,104,101,32,112,121,99,32,102,105,108,101, - 46,32,40,79,110,108,121,32,116,104,101,32,102,105,114,115, - 116,32,49,54,32,98,121,116,101,115,32,97,114,101,10,32, - 32,32,32,114,101,113,117,105,114,101,100,46,41,10,10,32, - 32,32,32,42,115,111,117,114,99,101,95,109,116,105,109,101, - 42,32,105,115,32,116,104,101,32,108,97,115,116,32,109,111, - 100,105,102,105,101,100,32,116,105,109,101,115,116,97,109,112, - 32,111,102,32,116,104,101,32,115,111,117,114,99,101,32,102, - 105,108,101,46,10,10,32,32,32,32,42,115,111,117,114,99, - 101,95,115,105,122,101,42,32,105,115,32,78,111,110,101,32, - 111,114,32,116,104,101,32,115,105,122,101,32,111,102,32,116, - 104,101,32,115,111,117,114,99,101,32,102,105,108,101,32,105, - 110,32,98,121,116,101,115,46,10,10,32,32,32,32,42,110, - 97,109,101,42,32,105,115,32,116,104,101,32,110,97,109,101, - 32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,98, - 101,105,110,103,32,105,109,112,111,114,116,101,100,46,32,73, - 116,32,105,115,32,117,115,101,100,32,102,111,114,32,108,111, - 103,103,105,110,103,46,10,10,32,32,32,32,42,101,120,99, - 95,100,101,116,97,105,108,115,42,32,105,115,32,97,32,100, - 105,99,116,105,111,110,97,114,121,32,112,97,115,115,101,100, - 32,116,111,32,73,109,112,111,114,116,69,114,114,111,114,32, - 105,102,32,105,116,32,114,97,105,115,101,100,32,102,111,114, - 10,32,32,32,32,105,109,112,114,111,118,101,100,32,100,101, - 98,117,103,103,105,110,103,46,10,10,32,32,32,32,65,110, - 32,73,109,112,111,114,116,69,114,114,111,114,32,105,115,32, - 114,97,105,115,101,100,32,105,102,32,116,104,101,32,98,121, - 116,101,99,111,100,101,32,105,115,32,115,116,97,108,101,46, - 10,10,32,32,32,32,114,127,0,0,0,233,12,0,0,0, - 108,3,0,0,0,255,127,255,127,3,0,122,22,98,121,116, - 101,99,111,100,101,32,105,115,32,115,116,97,108,101,32,102, - 111,114,32,122,2,123,125,78,114,126,0,0,0,41,4,114, - 19,0,0,0,114,116,0,0,0,114,130,0,0,0,114,101, - 0,0,0,41,6,114,54,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,100,0,0,0,114,132,0,0,0,114, - 77,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,23,95,118,97,108,105,100,97,116,101,95,116, - 105,109,101,115,116,97,109,112,95,112,121,99,210,1,0,0, - 115,14,0,0,0,0,19,24,1,10,1,12,1,12,1,8, - 1,24,1,114,137,0,0,0,99,4,0,0,0,0,0,0, - 0,4,0,0,0,3,0,0,0,67,0,0,0,115,38,0, - 0,0,124,0,100,1,100,2,133,2,25,0,124,1,107,3, - 114,34,116,0,100,3,124,2,155,2,157,2,102,1,124,3, - 142,1,130,1,100,4,83,0,41,5,97,243,1,0,0,86, - 97,108,105,100,97,116,101,32,97,32,104,97,115,104,45,98, - 97,115,101,100,32,112,121,99,32,98,121,32,99,104,101,99, - 107,105,110,103,32,116,104,101,32,114,101,97,108,32,115,111, - 117,114,99,101,32,104,97,115,104,32,97,103,97,105,110,115, - 116,32,116,104,101,32,111,110,101,32,105,110,10,32,32,32, - 32,116,104,101,32,112,121,99,32,104,101,97,100,101,114,46, + 100,0,83,0,41,2,78,41,4,218,10,95,95,109,111,100, + 117,108,101,95,95,218,8,95,95,110,97,109,101,95,95,218, + 12,95,95,113,117,97,108,110,97,109,101,95,95,218,7,95, + 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,53,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,5,95,119,114,97,112,151,1,0,0, + 115,8,0,0,0,0,1,10,1,10,1,22,1,122,26,95, + 99,104,101,99,107,95,110,97,109,101,46,60,108,111,99,97, + 108,115,62,46,95,119,114,97,112,41,1,78,41,3,218,10, + 95,98,111,111,116,115,116,114,97,112,114,115,0,0,0,218, + 9,78,97,109,101,69,114,114,111,114,41,3,114,104,0,0, + 0,114,105,0,0,0,114,115,0,0,0,114,2,0,0,0, + 41,1,114,104,0,0,0,114,4,0,0,0,218,11,95,99, + 104,101,99,107,95,110,97,109,101,132,1,0,0,115,14,0, + 0,0,0,8,14,7,2,1,10,1,14,2,14,5,10,1, + 114,118,0,0,0,99,2,0,0,0,0,0,0,0,5,0, + 0,0,6,0,0,0,67,0,0,0,115,60,0,0,0,124, + 0,160,0,124,1,161,1,92,2,125,2,125,3,124,2,100, + 1,107,8,114,56,116,1,124,3,131,1,114,56,100,2,125, + 4,116,2,160,3,124,4,160,4,124,3,100,3,25,0,161, + 1,116,5,161,2,1,0,124,2,83,0,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,60,0,0,0,41,6, + 218,11,102,105,110,100,95,108,111,97,100,101,114,114,31,0, + 0,0,114,61,0,0,0,114,62,0,0,0,114,48,0,0, + 0,218,13,73,109,112,111,114,116,87,97,114,110,105,110,103, + 41,5,114,102,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,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,17,95,102,105,110,100,95,109, + 111,100,117,108,101,95,115,104,105,109,160,1,0,0,115,10, + 0,0,0,0,10,14,1,16,1,4,1,22,1,114,125,0, + 0,0,99,3,0,0,0,0,0,0,0,6,0,0,0,4, + 0,0,0,67,0,0,0,115,158,0,0,0,124,0,100,1, + 100,2,133,2,25,0,125,3,124,3,116,0,107,3,114,60, + 100,3,124,1,155,2,100,4,124,3,155,2,157,4,125,4, + 116,1,160,2,100,5,124,4,161,2,1,0,116,3,124,4, + 102,1,124,2,142,1,130,1,116,4,124,0,131,1,100,6, + 107,0,114,102,100,7,124,1,155,2,157,2,125,4,116,1, + 160,2,100,5,124,4,161,2,1,0,116,5,124,4,131,1, + 130,1,116,6,124,0,100,2,100,8,133,2,25,0,131,1, + 125,5,124,5,100,9,64,0,114,154,100,10,124,5,155,2, + 100,11,124,1,155,2,157,4,125,4,116,3,124,4,102,1, + 124,2,142,1,130,1,124,5,83,0,41,12,97,84,2,0, + 0,80,101,114,102,111,114,109,32,98,97,115,105,99,32,118, + 97,108,105,100,105,116,121,32,99,104,101,99,107,105,110,103, + 32,111,102,32,97,32,112,121,99,32,104,101,97,100,101,114, + 32,97,110,100,32,114,101,116,117,114,110,32,116,104,101,32, + 102,108,97,103,115,32,102,105,101,108,100,44,10,32,32,32, + 32,119,104,105,99,104,32,100,101,116,101,114,109,105,110,101, + 115,32,104,111,119,32,116,104,101,32,112,121,99,32,115,104, + 111,117,108,100,32,98,101,32,102,117,114,116,104,101,114,32, + 118,97,108,105,100,97,116,101,100,32,97,103,97,105,110,115, + 116,32,116,104,101,32,115,111,117,114,99,101,46,10,10,32, + 32,32,32,42,100,97,116,97,42,32,105,115,32,116,104,101, + 32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101, + 32,112,121,99,32,102,105,108,101,46,32,40,79,110,108,121, + 32,116,104,101,32,102,105,114,115,116,32,49,54,32,98,121, + 116,101,115,32,97,114,101,10,32,32,32,32,114,101,113,117, + 105,114,101,100,44,32,116,104,111,117,103,104,46,41,10,10, + 32,32,32,32,42,110,97,109,101,42,32,105,115,32,116,104, + 101,32,110,97,109,101,32,111,102,32,116,104,101,32,109,111, + 100,117,108,101,32,98,101,105,110,103,32,105,109,112,111,114, + 116,101,100,46,32,73,116,32,105,115,32,117,115,101,100,32, + 102,111,114,32,108,111,103,103,105,110,103,46,10,10,32,32, + 32,32,42,101,120,99,95,100,101,116,97,105,108,115,42,32, + 105,115,32,97,32,100,105,99,116,105,111,110,97,114,121,32, + 112,97,115,115,101,100,32,116,111,32,73,109,112,111,114,116, + 69,114,114,111,114,32,105,102,32,105,116,32,114,97,105,115, + 101,100,32,102,111,114,10,32,32,32,32,105,109,112,114,111, + 118,101,100,32,100,101,98,117,103,103,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, + 119,104,101,110,32,116,104,101,32,102,108,97,103,115,10,32, + 32,32,32,102,105,101,108,100,32,105,115,32,105,110,118,97, + 108,105,100,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,32,116,114,117,110,99,97,116,101,100,46,10, + 10,32,32,32,32,78,114,12,0,0,0,122,20,98,97,100, + 32,109,97,103,105,99,32,110,117,109,98,101,114,32,105,110, + 32,122,2,58,32,122,2,123,125,233,16,0,0,0,122,40, + 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,112,121,99,32,104,101, + 97,100,101,114,32,111,102,32,233,8,0,0,0,233,252,255, + 255,255,122,14,105,110,118,97,108,105,100,32,102,108,97,103, + 115,32,122,4,32,105,110,32,41,7,218,12,77,65,71,73, + 67,95,78,85,77,66,69,82,114,116,0,0,0,218,16,95, + 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,114, + 101,0,0,0,114,31,0,0,0,218,8,69,79,70,69,114, + 114,111,114,114,19,0,0,0,41,6,114,54,0,0,0,114, + 100,0,0,0,218,11,101,120,99,95,100,101,116,97,105,108, + 115,90,5,109,97,103,105,99,114,77,0,0,0,114,69,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,13,95,99,108,97,115,115,105,102,121,95,112,121,99, + 177,1,0,0,115,28,0,0,0,0,16,12,1,8,1,16, + 1,12,1,12,1,12,1,10,1,12,1,8,1,16,2,8, + 1,16,1,12,1,114,133,0,0,0,99,5,0,0,0,0, + 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, + 112,0,0,0,116,0,124,0,100,1,100,2,133,2,25,0, + 131,1,124,1,100,3,64,0,107,3,114,58,100,4,124,3, + 155,2,157,2,125,5,116,1,160,2,100,5,124,5,161,2, + 1,0,116,3,124,5,102,1,124,4,142,1,130,1,124,2, + 100,6,107,9,114,108,116,0,124,0,100,2,100,7,133,2, + 25,0,131,1,124,2,100,3,64,0,107,3,114,108,116,3, + 100,4,124,3,155,2,157,2,102,1,124,4,142,1,130,1, + 100,6,83,0,41,8,97,7,2,0,0,86,97,108,105,100, + 97,116,101,32,97,32,112,121,99,32,97,103,97,105,110,115, + 116,32,116,104,101,32,115,111,117,114,99,101,32,108,97,115, + 116,45,109,111,100,105,102,105,101,100,32,116,105,109,101,46, 10,10,32,32,32,32,42,100,97,116,97,42,32,105,115,32, 116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32, 116,104,101,32,112,121,99,32,102,105,108,101,46,32,40,79, 110,108,121,32,116,104,101,32,102,105,114,115,116,32,49,54, 32,98,121,116,101,115,32,97,114,101,10,32,32,32,32,114, 101,113,117,105,114,101,100,46,41,10,10,32,32,32,32,42, - 115,111,117,114,99,101,95,104,97,115,104,42,32,105,115,32, - 116,104,101,32,105,109,112,111,114,116,108,105,98,46,117,116, - 105,108,46,115,111,117,114,99,101,95,104,97,115,104,40,41, - 32,111,102,32,116,104,101,32,115,111,117,114,99,101,32,102, - 105,108,101,46,10,10,32,32,32,32,42,110,97,109,101,42, + 115,111,117,114,99,101,95,109,116,105,109,101,42,32,105,115, + 32,116,104,101,32,108,97,115,116,32,109,111,100,105,102,105, + 101,100,32,116,105,109,101,115,116,97,109,112,32,111,102,32, + 116,104,101,32,115,111,117,114,99,101,32,102,105,108,101,46, + 10,10,32,32,32,32,42,115,111,117,114,99,101,95,115,105, + 122,101,42,32,105,115,32,78,111,110,101,32,111,114,32,116, + 104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,115, + 111,117,114,99,101,32,102,105,108,101,32,105,110,32,98,121, + 116,101,115,46,10,10,32,32,32,32,42,110,97,109,101,42, 32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32, 116,104,101,32,109,111,100,117,108,101,32,98,101,105,110,103, 32,105,109,112,111,114,116,101,100,46,32,73,116,32,105,115, @@ -735,1819 +686,1867 @@ const unsigned char _Py_M__importlib_external[] = { 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, 101,100,32,105,102,32,116,104,101,32,98,121,116,101,99,111, 100,101,32,105,115,32,115,116,97,108,101,46,10,10,32,32, - 32,32,114,127,0,0,0,114,126,0,0,0,122,46,104,97, - 115,104,32,105,110,32,98,121,116,101,99,111,100,101,32,100, - 111,101,115,110,39,116,32,109,97,116,99,104,32,104,97,115, - 104,32,111,102,32,115,111,117,114,99,101,32,78,41,1,114, - 101,0,0,0,41,4,114,54,0,0,0,218,11,115,111,117, - 114,99,101,95,104,97,115,104,114,100,0,0,0,114,132,0, + 32,32,114,127,0,0,0,233,12,0,0,0,108,3,0,0, + 0,255,127,255,127,3,0,122,22,98,121,116,101,99,111,100, + 101,32,105,115,32,115,116,97,108,101,32,102,111,114,32,122, + 2,123,125,78,114,126,0,0,0,41,4,114,19,0,0,0, + 114,116,0,0,0,114,130,0,0,0,114,101,0,0,0,41, + 6,114,54,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,100,0,0,0,114,132,0,0,0,114,77,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 23,95,118,97,108,105,100,97,116,101,95,116,105,109,101,115, + 116,97,109,112,95,112,121,99,210,1,0,0,115,14,0,0, + 0,0,19,24,1,10,1,12,1,12,1,8,1,24,1,114, + 137,0,0,0,99,4,0,0,0,0,0,0,0,4,0,0, + 0,3,0,0,0,67,0,0,0,115,38,0,0,0,124,0, + 100,1,100,2,133,2,25,0,124,1,107,3,114,34,116,0, + 100,3,124,2,155,2,157,2,102,1,124,3,142,1,130,1, + 100,4,83,0,41,5,97,243,1,0,0,86,97,108,105,100, + 97,116,101,32,97,32,104,97,115,104,45,98,97,115,101,100, + 32,112,121,99,32,98,121,32,99,104,101,99,107,105,110,103, + 32,116,104,101,32,114,101,97,108,32,115,111,117,114,99,101, + 32,104,97,115,104,32,97,103,97,105,110,115,116,32,116,104, + 101,32,111,110,101,32,105,110,10,32,32,32,32,116,104,101, + 32,112,121,99,32,104,101,97,100,101,114,46,10,10,32,32, + 32,32,42,100,97,116,97,42,32,105,115,32,116,104,101,32, + 99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32, + 112,121,99,32,102,105,108,101,46,32,40,79,110,108,121,32, + 116,104,101,32,102,105,114,115,116,32,49,54,32,98,121,116, + 101,115,32,97,114,101,10,32,32,32,32,114,101,113,117,105, + 114,101,100,46,41,10,10,32,32,32,32,42,115,111,117,114, + 99,101,95,104,97,115,104,42,32,105,115,32,116,104,101,32, + 105,109,112,111,114,116,108,105,98,46,117,116,105,108,46,115, + 111,117,114,99,101,95,104,97,115,104,40,41,32,111,102,32, + 116,104,101,32,115,111,117,114,99,101,32,102,105,108,101,46, + 10,10,32,32,32,32,42,110,97,109,101,42,32,105,115,32, + 116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32, + 109,111,100,117,108,101,32,98,101,105,110,103,32,105,109,112, + 111,114,116,101,100,46,32,73,116,32,105,115,32,117,115,101, + 100,32,102,111,114,32,108,111,103,103,105,110,103,46,10,10, + 32,32,32,32,42,101,120,99,95,100,101,116,97,105,108,115, + 42,32,105,115,32,97,32,100,105,99,116,105,111,110,97,114, + 121,32,112,97,115,115,101,100,32,116,111,32,73,109,112,111, + 114,116,69,114,114,111,114,32,105,102,32,105,116,32,114,97, + 105,115,101,100,32,102,111,114,10,32,32,32,32,105,109,112, + 114,111,118,101,100,32,100,101,98,117,103,103,105,110,103,46, + 10,10,32,32,32,32,65,110,32,73,109,112,111,114,116,69, + 114,114,111,114,32,105,115,32,114,97,105,115,101,100,32,105, + 102,32,116,104,101,32,98,121,116,101,99,111,100,101,32,105, + 115,32,115,116,97,108,101,46,10,10,32,32,32,32,114,127, + 0,0,0,114,126,0,0,0,122,46,104,97,115,104,32,105, + 110,32,98,121,116,101,99,111,100,101,32,100,111,101,115,110, + 39,116,32,109,97,116,99,104,32,104,97,115,104,32,111,102, + 32,115,111,117,114,99,101,32,78,41,1,114,101,0,0,0, + 41,4,114,54,0,0,0,218,11,115,111,117,114,99,101,95, + 104,97,115,104,114,100,0,0,0,114,132,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,218,18,95, + 118,97,108,105,100,97,116,101,95,104,97,115,104,95,112,121, + 99,238,1,0,0,115,8,0,0,0,0,17,16,1,2,1, + 10,1,114,139,0,0,0,99,4,0,0,0,0,0,0,0, + 5,0,0,0,5,0,0,0,67,0,0,0,115,80,0,0, + 0,116,0,160,1,124,0,161,1,125,4,116,2,124,4,116, + 3,131,2,114,56,116,4,160,5,100,1,124,2,161,2,1, + 0,124,3,100,2,107,9,114,52,116,6,160,7,124,4,124, + 3,161,2,1,0,124,4,83,0,116,8,100,3,160,9,124, + 2,161,1,124,1,124,2,100,4,141,3,130,1,100,2,83, + 0,41,5,122,35,67,111,109,112,105,108,101,32,98,121,116, + 101,99,111,100,101,32,97,115,32,102,111,117,110,100,32,105, + 110,32,97,32,112,121,99,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,41,2,114,100,0,0,0, + 114,35,0,0,0,41,10,218,7,109,97,114,115,104,97,108, + 90,5,108,111,97,100,115,218,10,105,115,105,110,115,116,97, + 110,99,101,218,10,95,99,111,100,101,95,116,121,112,101,114, + 116,0,0,0,114,130,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,101,0,0,0,114,48,0,0,0,41,5,114,54,0, + 0,0,114,100,0,0,0,114,91,0,0,0,114,92,0,0, + 0,218,4,99,111,100,101,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,218,17,95,99,111,109,112,105,108,101, + 95,98,121,116,101,99,111,100,101,6,2,0,0,115,16,0, + 0,0,0,2,10,1,10,1,12,1,8,1,12,1,4,2, + 10,1,114,145,0,0,0,114,60,0,0,0,99,3,0,0, + 0,0,0,0,0,4,0,0,0,5,0,0,0,67,0,0, + 0,115,70,0,0,0,116,0,116,1,131,1,125,3,124,3, + 160,2,116,3,100,1,131,1,161,1,1,0,124,3,160,2, + 116,3,124,1,131,1,161,1,1,0,124,3,160,2,116,3, + 124,2,131,1,161,1,1,0,124,3,160,2,116,4,160,5, + 124,0,161,1,161,1,1,0,124,3,83,0,41,2,122,43, + 80,114,111,100,117,99,101,32,116,104,101,32,100,97,116,97, + 32,102,111,114,32,97,32,116,105,109,101,115,116,97,109,112, + 45,98,97,115,101,100,32,112,121,99,46,114,60,0,0,0, + 41,6,218,9,98,121,116,101,97,114,114,97,121,114,129,0, + 0,0,218,6,101,120,116,101,110,100,114,17,0,0,0,114, + 140,0,0,0,218,5,100,117,109,112,115,41,4,114,144,0, + 0,0,218,5,109,116,105,109,101,114,136,0,0,0,114,54, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,22,95,99,111,100,101,95,116,111,95,116,105,109, + 101,115,116,97,109,112,95,112,121,99,19,2,0,0,115,12, + 0,0,0,0,2,8,1,14,1,14,1,14,1,16,1,114, + 150,0,0,0,84,99,3,0,0,0,0,0,0,0,5,0, + 0,0,5,0,0,0,67,0,0,0,115,80,0,0,0,116, + 0,116,1,131,1,125,3,100,1,124,2,100,1,62,0,66, + 0,125,4,124,3,160,2,116,3,124,4,131,1,161,1,1, + 0,116,4,124,1,131,1,100,2,107,2,115,50,116,5,130, + 1,124,3,160,2,124,1,161,1,1,0,124,3,160,2,116, + 6,160,7,124,0,161,1,161,1,1,0,124,3,83,0,41, + 3,122,38,80,114,111,100,117,99,101,32,116,104,101,32,100, + 97,116,97,32,102,111,114,32,97,32,104,97,115,104,45,98, + 97,115,101,100,32,112,121,99,46,114,29,0,0,0,114,127, + 0,0,0,41,8,114,146,0,0,0,114,129,0,0,0,114, + 147,0,0,0,114,17,0,0,0,114,31,0,0,0,218,14, + 65,115,115,101,114,116,105,111,110,69,114,114,111,114,114,140, + 0,0,0,114,148,0,0,0,41,5,114,144,0,0,0,114, + 138,0,0,0,90,7,99,104,101,99,107,101,100,114,54,0, + 0,0,114,69,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,218,17,95,99,111,100,101,95,116,111, + 95,104,97,115,104,95,112,121,99,29,2,0,0,115,14,0, + 0,0,0,2,8,1,12,1,14,1,16,1,10,1,16,1, + 114,152,0,0,0,99,1,0,0,0,0,0,0,0,5,0, + 0,0,6,0,0,0,67,0,0,0,115,62,0,0,0,100, + 1,100,2,108,0,125,1,116,1,160,2,124,0,161,1,106, + 3,125,2,124,1,160,4,124,2,161,1,125,3,116,1,160, + 5,100,2,100,3,161,2,125,4,124,4,160,6,124,0,160, + 6,124,3,100,1,25,0,161,1,161,1,83,0,41,4,122, + 121,68,101,99,111,100,101,32,98,121,116,101,115,32,114,101, + 112,114,101,115,101,110,116,105,110,103,32,115,111,117,114,99, + 101,32,99,111,100,101,32,97,110,100,32,114,101,116,117,114, + 110,32,116,104,101,32,115,116,114,105,110,103,46,10,10,32, + 32,32,32,85,110,105,118,101,114,115,97,108,32,110,101,119, + 108,105,110,101,32,115,117,112,112,111,114,116,32,105,115,32, + 117,115,101,100,32,105,110,32,116,104,101,32,100,101,99,111, + 100,105,110,103,46,10,32,32,32,32,114,60,0,0,0,78, + 84,41,7,218,8,116,111,107,101,110,105,122,101,114,50,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,153,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,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 13,100,101,99,111,100,101,95,115,111,117,114,99,101,40,2, + 0,0,115,10,0,0,0,0,5,8,1,12,1,10,1,12, + 1,114,157,0,0,0,41,2,114,122,0,0,0,218,26,115, + 117,98,109,111,100,117,108,101,95,115,101,97,114,99,104,95, + 108,111,99,97,116,105,111,110,115,99,2,0,0,0,2,0, + 0,0,9,0,0,0,19,0,0,0,67,0,0,0,115,18, + 1,0,0,124,1,100,1,107,8,114,60,100,2,125,1,116, + 0,124,2,100,3,131,2,114,70,121,14,124,2,160,1,124, + 0,161,1,125,1,87,0,113,70,4,0,116,2,107,10,114, + 56,1,0,1,0,1,0,89,0,113,70,88,0,110,10,116, + 3,160,4,124,1,161,1,125,1,116,5,106,6,124,0,124, + 2,124,1,100,4,141,3,125,4,100,5,124,4,95,7,124, + 2,100,1,107,8,114,156,120,54,116,8,131,0,68,0,93, + 40,92,2,125,5,125,6,124,1,160,9,116,10,124,6,131, + 1,161,1,114,108,124,5,124,0,124,1,131,2,125,2,124, + 2,124,4,95,11,80,0,113,108,87,0,100,1,83,0,124, + 3,116,12,107,8,114,222,116,0,124,2,100,6,131,2,114, + 228,121,14,124,2,160,13,124,0,161,1,125,7,87,0,110, + 20,4,0,116,2,107,10,114,208,1,0,1,0,1,0,89, + 0,113,228,88,0,124,7,114,228,103,0,124,4,95,14,110, + 6,124,3,124,4,95,14,124,4,106,14,103,0,107,2,144, + 1,114,14,124,1,144,1,114,14,116,15,124,1,131,1,100, + 7,25,0,125,8,124,4,106,14,160,16,124,8,161,1,1, + 0,124,4,83,0,41,8,97,61,1,0,0,82,101,116,117, + 114,110,32,97,32,109,111,100,117,108,101,32,115,112,101,99, + 32,98,97,115,101,100,32,111,110,32,97,32,102,105,108,101, + 32,108,111,99,97,116,105,111,110,46,10,10,32,32,32,32, + 84,111,32,105,110,100,105,99,97,116,101,32,116,104,97,116, + 32,116,104,101,32,109,111,100,117,108,101,32,105,115,32,97, + 32,112,97,99,107,97,103,101,44,32,115,101,116,10,32,32, + 32,32,115,117,98,109,111,100,117,108,101,95,115,101,97,114, + 99,104,95,108,111,99,97,116,105,111,110,115,32,116,111,32, + 97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116, + 111,114,121,32,112,97,116,104,115,46,32,32,65,110,10,32, + 32,32,32,101,109,112,116,121,32,108,105,115,116,32,105,115, + 32,115,117,102,102,105,99,105,101,110,116,44,32,116,104,111, + 117,103,104,32,105,116,115,32,110,111,116,32,111,116,104,101, + 114,119,105,115,101,32,117,115,101,102,117,108,32,116,111,32, + 116,104,101,10,32,32,32,32,105,109,112,111,114,116,32,115, + 121,115,116,101,109,46,10,10,32,32,32,32,84,104,101,32, + 108,111,97,100,101,114,32,109,117,115,116,32,116,97,107,101, + 32,97,32,115,112,101,99,32,97,115,32,105,116,115,32,111, + 110,108,121,32,95,95,105,110,105,116,95,95,40,41,32,97, + 114,103,46,10,10,32,32,32,32,78,122,9,60,117,110,107, + 110,111,119,110,62,218,12,103,101,116,95,102,105,108,101,110, + 97,109,101,41,1,218,6,111,114,105,103,105,110,84,218,10, + 105,115,95,112,97,99,107,97,103,101,114,60,0,0,0,41, + 17,114,110,0,0,0,114,159,0,0,0,114,101,0,0,0, + 114,1,0,0,0,114,65,0,0,0,114,116,0,0,0,218, + 10,77,111,100,117,108,101,83,112,101,99,90,13,95,115,101, + 116,95,102,105,108,101,97,116,116,114,218,27,95,103,101,116, + 95,115,117,112,112,111,114,116,101,100,95,102,105,108,101,95, + 108,111,97,100,101,114,115,114,94,0,0,0,114,95,0,0, + 0,114,122,0,0,0,218,9,95,80,79,80,85,76,65,84, + 69,114,161,0,0,0,114,158,0,0,0,114,38,0,0,0, + 218,6,97,112,112,101,110,100,41,9,114,100,0,0,0,90, + 8,108,111,99,97,116,105,111,110,114,122,0,0,0,114,158, + 0,0,0,218,4,115,112,101,99,218,12,108,111,97,100,101, + 114,95,99,108,97,115,115,218,8,115,117,102,102,105,120,101, + 115,114,161,0,0,0,90,7,100,105,114,110,97,109,101,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,23, + 115,112,101,99,95,102,114,111,109,95,102,105,108,101,95,108, + 111,99,97,116,105,111,110,57,2,0,0,115,62,0,0,0, + 0,12,8,4,4,1,10,2,2,1,14,1,14,1,8,2, + 10,8,16,1,6,3,8,1,16,1,14,1,10,1,6,1, + 6,2,4,3,8,2,10,1,2,1,14,1,14,1,6,2, + 4,1,8,2,6,1,12,1,6,1,12,1,12,2,114,169, + 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 4,0,0,0,64,0,0,0,115,80,0,0,0,101,0,90, + 1,100,0,90,2,100,1,90,3,100,2,90,4,100,3,90, + 5,100,4,90,6,101,7,100,5,100,6,132,0,131,1,90, + 8,101,7,100,7,100,8,132,0,131,1,90,9,101,7,100, + 14,100,10,100,11,132,1,131,1,90,10,101,7,100,15,100, + 12,100,13,132,1,131,1,90,11,100,9,83,0,41,16,218, + 21,87,105,110,100,111,119,115,82,101,103,105,115,116,114,121, + 70,105,110,100,101,114,122,62,77,101,116,97,32,112,97,116, + 104,32,102,105,110,100,101,114,32,102,111,114,32,109,111,100, + 117,108,101,115,32,100,101,99,108,97,114,101,100,32,105,110, + 32,116,104,101,32,87,105,110,100,111,119,115,32,114,101,103, + 105,115,116,114,121,46,122,59,83,111,102,116,119,97,114,101, + 92,80,121,116,104,111,110,92,80,121,116,104,111,110,67,111, + 114,101,92,123,115,121,115,95,118,101,114,115,105,111,110,125, + 92,77,111,100,117,108,101,115,92,123,102,117,108,108,110,97, + 109,101,125,122,65,83,111,102,116,119,97,114,101,92,80,121, + 116,104,111,110,92,80,121,116,104,111,110,67,111,114,101,92, + 123,115,121,115,95,118,101,114,115,105,111,110,125,92,77,111, + 100,117,108,101,115,92,123,102,117,108,108,110,97,109,101,125, + 92,68,101,98,117,103,70,99,2,0,0,0,0,0,0,0, + 2,0,0,0,11,0,0,0,67,0,0,0,115,50,0,0, + 0,121,14,116,0,160,1,116,0,106,2,124,1,161,2,83, + 0,4,0,116,3,107,10,114,44,1,0,1,0,1,0,116, + 0,160,1,116,0,106,4,124,1,161,2,83,0,88,0,100, + 0,83,0,41,1,78,41,5,218,7,95,119,105,110,114,101, + 103,90,7,79,112,101,110,75,101,121,90,17,72,75,69,89, + 95,67,85,82,82,69,78,84,95,85,83,69,82,114,40,0, + 0,0,90,18,72,75,69,89,95,76,79,67,65,76,95,77, + 65,67,72,73,78,69,41,2,218,3,99,108,115,114,3,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,18,95,118,97,108,105,100,97,116,101,95,104,97,115, - 104,95,112,121,99,238,1,0,0,115,8,0,0,0,0,17, - 16,1,2,1,10,1,114,139,0,0,0,99,4,0,0,0, - 0,0,0,0,5,0,0,0,5,0,0,0,67,0,0,0, - 115,80,0,0,0,116,0,160,1,124,0,161,1,125,4,116, - 2,124,4,116,3,131,2,114,56,116,4,160,5,100,1,124, - 2,161,2,1,0,124,3,100,2,107,9,114,52,116,6,160, - 7,124,4,124,3,161,2,1,0,124,4,83,0,116,8,100, - 3,160,9,124,2,161,1,124,1,124,2,100,4,141,3,130, - 1,100,2,83,0,41,5,122,35,67,111,109,112,105,108,101, - 32,98,121,116,101,99,111,100,101,32,97,115,32,102,111,117, - 110,100,32,105,110,32,97,32,112,121,99,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,41,2,114, - 100,0,0,0,114,35,0,0,0,41,10,218,7,109,97,114, - 115,104,97,108,90,5,108,111,97,100,115,218,10,105,115,105, - 110,115,116,97,110,99,101,218,10,95,99,111,100,101,95,116, - 121,112,101,114,116,0,0,0,114,130,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,101,0,0,0,114,48,0,0,0,41, - 5,114,54,0,0,0,114,100,0,0,0,114,91,0,0,0, - 114,92,0,0,0,218,4,99,111,100,101,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,218,17,95,99,111,109, - 112,105,108,101,95,98,121,116,101,99,111,100,101,6,2,0, - 0,115,16,0,0,0,0,2,10,1,10,1,12,1,8,1, - 12,1,4,2,10,1,114,145,0,0,0,114,60,0,0,0, - 99,3,0,0,0,0,0,0,0,4,0,0,0,5,0,0, - 0,67,0,0,0,115,70,0,0,0,116,0,116,1,131,1, - 125,3,124,3,160,2,116,3,100,1,131,1,161,1,1,0, - 124,3,160,2,116,3,124,1,131,1,161,1,1,0,124,3, - 160,2,116,3,124,2,131,1,161,1,1,0,124,3,160,2, - 116,4,160,5,124,0,161,1,161,1,1,0,124,3,83,0, - 41,2,122,43,80,114,111,100,117,99,101,32,116,104,101,32, - 100,97,116,97,32,102,111,114,32,97,32,116,105,109,101,115, - 116,97,109,112,45,98,97,115,101,100,32,112,121,99,46,114, - 60,0,0,0,41,6,218,9,98,121,116,101,97,114,114,97, - 121,114,129,0,0,0,218,6,101,120,116,101,110,100,114,17, - 0,0,0,114,140,0,0,0,218,5,100,117,109,112,115,41, - 4,114,144,0,0,0,218,5,109,116,105,109,101,114,136,0, - 0,0,114,54,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,218,22,95,99,111,100,101,95,116,111, - 95,116,105,109,101,115,116,97,109,112,95,112,121,99,19,2, - 0,0,115,12,0,0,0,0,2,8,1,14,1,14,1,14, - 1,16,1,114,150,0,0,0,84,99,3,0,0,0,0,0, - 0,0,5,0,0,0,5,0,0,0,67,0,0,0,115,80, - 0,0,0,116,0,116,1,131,1,125,3,100,1,124,2,100, - 1,62,0,66,0,125,4,124,3,160,2,116,3,124,4,131, - 1,161,1,1,0,116,4,124,1,131,1,100,2,107,2,115, - 50,116,5,130,1,124,3,160,2,124,1,161,1,1,0,124, - 3,160,2,116,6,160,7,124,0,161,1,161,1,1,0,124, - 3,83,0,41,3,122,38,80,114,111,100,117,99,101,32,116, - 104,101,32,100,97,116,97,32,102,111,114,32,97,32,104,97, - 115,104,45,98,97,115,101,100,32,112,121,99,46,114,29,0, - 0,0,114,127,0,0,0,41,8,114,146,0,0,0,114,129, - 0,0,0,114,147,0,0,0,114,17,0,0,0,114,31,0, - 0,0,218,14,65,115,115,101,114,116,105,111,110,69,114,114, - 111,114,114,140,0,0,0,114,148,0,0,0,41,5,114,144, - 0,0,0,114,138,0,0,0,90,7,99,104,101,99,107,101, - 100,114,54,0,0,0,114,69,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,218,17,95,99,111,100, - 101,95,116,111,95,104,97,115,104,95,112,121,99,29,2,0, - 0,115,14,0,0,0,0,2,8,1,12,1,14,1,16,1, - 10,1,16,1,114,152,0,0,0,99,1,0,0,0,0,0, - 0,0,5,0,0,0,6,0,0,0,67,0,0,0,115,62, - 0,0,0,100,1,100,2,108,0,125,1,116,1,160,2,124, - 0,161,1,106,3,125,2,124,1,160,4,124,2,161,1,125, - 3,116,1,160,5,100,2,100,3,161,2,125,4,124,4,160, - 6,124,0,160,6,124,3,100,1,25,0,161,1,161,1,83, - 0,41,4,122,121,68,101,99,111,100,101,32,98,121,116,101, - 115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,115, - 111,117,114,99,101,32,99,111,100,101,32,97,110,100,32,114, - 101,116,117,114,110,32,116,104,101,32,115,116,114,105,110,103, - 46,10,10,32,32,32,32,85,110,105,118,101,114,115,97,108, - 32,110,101,119,108,105,110,101,32,115,117,112,112,111,114,116, - 32,105,115,32,117,115,101,100,32,105,110,32,116,104,101,32, - 100,101,99,111,100,105,110,103,46,10,32,32,32,32,114,60, - 0,0,0,78,84,41,7,218,8,116,111,107,101,110,105,122, - 101,114,50,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,153,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,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,13,100,101,99,111,100,101,95,115,111,117,114, - 99,101,40,2,0,0,115,10,0,0,0,0,5,8,1,12, - 1,10,1,12,1,114,157,0,0,0,41,2,114,122,0,0, - 0,218,26,115,117,98,109,111,100,117,108,101,95,115,101,97, - 114,99,104,95,108,111,99,97,116,105,111,110,115,99,2,0, - 0,0,2,0,0,0,9,0,0,0,19,0,0,0,67,0, - 0,0,115,18,1,0,0,124,1,100,1,107,8,114,60,100, - 2,125,1,116,0,124,2,100,3,131,2,114,70,121,14,124, - 2,160,1,124,0,161,1,125,1,87,0,113,70,4,0,116, - 2,107,10,114,56,1,0,1,0,1,0,89,0,113,70,88, - 0,110,10,116,3,160,4,124,1,161,1,125,1,116,5,106, - 6,124,0,124,2,124,1,100,4,141,3,125,4,100,5,124, - 4,95,7,124,2,100,1,107,8,114,156,120,54,116,8,131, - 0,68,0,93,40,92,2,125,5,125,6,124,1,160,9,116, - 10,124,6,131,1,161,1,114,108,124,5,124,0,124,1,131, - 2,125,2,124,2,124,4,95,11,80,0,113,108,87,0,100, - 1,83,0,124,3,116,12,107,8,114,222,116,0,124,2,100, - 6,131,2,114,228,121,14,124,2,160,13,124,0,161,1,125, - 7,87,0,110,20,4,0,116,2,107,10,114,208,1,0,1, - 0,1,0,89,0,113,228,88,0,124,7,114,228,103,0,124, - 4,95,14,110,6,124,3,124,4,95,14,124,4,106,14,103, - 0,107,2,144,1,114,14,124,1,144,1,114,14,116,15,124, - 1,131,1,100,7,25,0,125,8,124,4,106,14,160,16,124, - 8,161,1,1,0,124,4,83,0,41,8,97,61,1,0,0, - 82,101,116,117,114,110,32,97,32,109,111,100,117,108,101,32, - 115,112,101,99,32,98,97,115,101,100,32,111,110,32,97,32, - 102,105,108,101,32,108,111,99,97,116,105,111,110,46,10,10, - 32,32,32,32,84,111,32,105,110,100,105,99,97,116,101,32, - 116,104,97,116,32,116,104,101,32,109,111,100,117,108,101,32, - 105,115,32,97,32,112,97,99,107,97,103,101,44,32,115,101, - 116,10,32,32,32,32,115,117,98,109,111,100,117,108,101,95, - 115,101,97,114,99,104,95,108,111,99,97,116,105,111,110,115, - 32,116,111,32,97,32,108,105,115,116,32,111,102,32,100,105, - 114,101,99,116,111,114,121,32,112,97,116,104,115,46,32,32, - 65,110,10,32,32,32,32,101,109,112,116,121,32,108,105,115, - 116,32,105,115,32,115,117,102,102,105,99,105,101,110,116,44, - 32,116,104,111,117,103,104,32,105,116,115,32,110,111,116,32, - 111,116,104,101,114,119,105,115,101,32,117,115,101,102,117,108, - 32,116,111,32,116,104,101,10,32,32,32,32,105,109,112,111, - 114,116,32,115,121,115,116,101,109,46,10,10,32,32,32,32, - 84,104,101,32,108,111,97,100,101,114,32,109,117,115,116,32, - 116,97,107,101,32,97,32,115,112,101,99,32,97,115,32,105, - 116,115,32,111,110,108,121,32,95,95,105,110,105,116,95,95, - 40,41,32,97,114,103,46,10,10,32,32,32,32,78,122,9, - 60,117,110,107,110,111,119,110,62,218,12,103,101,116,95,102, - 105,108,101,110,97,109,101,41,1,218,6,111,114,105,103,105, - 110,84,218,10,105,115,95,112,97,99,107,97,103,101,114,60, - 0,0,0,41,17,114,110,0,0,0,114,159,0,0,0,114, - 101,0,0,0,114,1,0,0,0,114,65,0,0,0,114,116, - 0,0,0,218,10,77,111,100,117,108,101,83,112,101,99,90, - 13,95,115,101,116,95,102,105,108,101,97,116,116,114,218,27, - 95,103,101,116,95,115,117,112,112,111,114,116,101,100,95,102, - 105,108,101,95,108,111,97,100,101,114,115,114,94,0,0,0, - 114,95,0,0,0,114,122,0,0,0,218,9,95,80,79,80, - 85,76,65,84,69,114,161,0,0,0,114,158,0,0,0,114, - 38,0,0,0,218,6,97,112,112,101,110,100,41,9,114,100, - 0,0,0,90,8,108,111,99,97,116,105,111,110,114,122,0, - 0,0,114,158,0,0,0,218,4,115,112,101,99,218,12,108, - 111,97,100,101,114,95,99,108,97,115,115,218,8,115,117,102, - 102,105,120,101,115,114,161,0,0,0,90,7,100,105,114,110, + 0,218,14,95,111,112,101,110,95,114,101,103,105,115,116,114, + 121,137,2,0,0,115,8,0,0,0,0,2,2,1,14,1, + 14,1,122,36,87,105,110,100,111,119,115,82,101,103,105,115, + 116,114,121,70,105,110,100,101,114,46,95,111,112,101,110,95, + 114,101,103,105,115,116,114,121,99,2,0,0,0,0,0,0, + 0,6,0,0,0,17,0,0,0,67,0,0,0,115,112,0, + 0,0,124,0,106,0,114,14,124,0,106,1,125,2,110,6, + 124,0,106,2,125,2,124,2,106,3,124,1,100,1,116,4, + 106,5,100,0,100,2,133,2,25,0,22,0,100,3,141,2, + 125,3,121,38,124,0,160,6,124,3,161,1,143,18,125,4, + 116,7,160,8,124,4,100,4,161,2,125,5,87,0,100,0, + 81,0,82,0,88,0,87,0,110,20,4,0,116,9,107,10, + 114,106,1,0,1,0,1,0,100,0,83,0,88,0,124,5, + 83,0,41,5,78,122,5,37,100,46,37,100,114,57,0,0, + 0,41,2,114,121,0,0,0,90,11,115,121,115,95,118,101, + 114,115,105,111,110,114,30,0,0,0,41,10,218,11,68,69, + 66,85,71,95,66,85,73,76,68,218,18,82,69,71,73,83, + 84,82,89,95,75,69,89,95,68,69,66,85,71,218,12,82, + 69,71,73,83,84,82,89,95,75,69,89,114,48,0,0,0, + 114,6,0,0,0,218,12,118,101,114,115,105,111,110,95,105, + 110,102,111,114,173,0,0,0,114,171,0,0,0,90,10,81, + 117,101,114,121,86,97,108,117,101,114,40,0,0,0,41,6, + 114,172,0,0,0,114,121,0,0,0,90,12,114,101,103,105, + 115,116,114,121,95,107,101,121,114,3,0,0,0,90,4,104, + 107,101,121,218,8,102,105,108,101,112,97,116,104,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,218,16,95,115, + 101,97,114,99,104,95,114,101,103,105,115,116,114,121,144,2, + 0,0,115,22,0,0,0,0,2,6,1,8,2,6,1,6, + 1,22,1,2,1,12,1,26,1,14,1,6,1,122,38,87, + 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, + 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,120,0,0,0, + 124,0,160,0,124,1,161,1,125,4,124,4,100,0,107,8, + 114,22,100,0,83,0,121,12,116,1,124,4,131,1,1,0, + 87,0,110,20,4,0,116,2,107,10,114,54,1,0,1,0, + 1,0,100,0,83,0,88,0,120,58,116,3,131,0,68,0, + 93,48,92,2,125,5,125,6,124,4,160,4,116,5,124,6, + 131,1,161,1,114,64,116,6,106,7,124,1,124,5,124,1, + 124,4,131,2,124,4,100,1,141,3,125,7,124,7,83,0, + 113,64,87,0,100,0,83,0,41,2,78,41,1,114,160,0, + 0,0,41,8,114,179,0,0,0,114,39,0,0,0,114,40, + 0,0,0,114,163,0,0,0,114,94,0,0,0,114,95,0, + 0,0,114,116,0,0,0,218,16,115,112,101,99,95,102,114, + 111,109,95,108,111,97,100,101,114,41,8,114,172,0,0,0, + 114,121,0,0,0,114,35,0,0,0,218,6,116,97,114,103, + 101,116,114,178,0,0,0,114,122,0,0,0,114,168,0,0, + 0,114,166,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,9,102,105,110,100,95,115,112,101,99, + 159,2,0,0,115,26,0,0,0,0,2,10,1,8,1,4, + 1,2,1,12,1,14,1,6,1,16,1,14,1,6,1,8, + 1,8,1,122,31,87,105,110,100,111,119,115,82,101,103,105, + 115,116,114,121,70,105,110,100,101,114,46,102,105,110,100,95, + 115,112,101,99,99,3,0,0,0,0,0,0,0,4,0,0, + 0,4,0,0,0,67,0,0,0,115,34,0,0,0,124,0, + 160,0,124,1,124,2,161,2,125,3,124,3,100,1,107,9, + 114,26,124,3,106,1,83,0,100,1,83,0,100,1,83,0, + 41,2,122,108,70,105,110,100,32,109,111,100,117,108,101,32, + 110,97,109,101,100,32,105,110,32,116,104,101,32,114,101,103, + 105,115,116,114,121,46,10,10,32,32,32,32,32,32,32,32, + 84,104,105,115,32,109,101,116,104,111,100,32,105,115,32,100, + 101,112,114,101,99,97,116,101,100,46,32,32,85,115,101,32, + 101,120,101,99,95,109,111,100,117,108,101,40,41,32,105,110, + 115,116,101,97,100,46,10,10,32,32,32,32,32,32,32,32, + 78,41,2,114,182,0,0,0,114,122,0,0,0,41,4,114, + 172,0,0,0,114,121,0,0,0,114,35,0,0,0,114,166, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,175, + 2,0,0,115,8,0,0,0,0,7,12,1,8,1,6,2, + 122,33,87,105,110,100,111,119,115,82,101,103,105,115,116,114, + 121,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, + 117,108,101,41,2,78,78,41,1,78,41,12,114,107,0,0, + 0,114,106,0,0,0,114,108,0,0,0,114,109,0,0,0, + 114,176,0,0,0,114,175,0,0,0,114,174,0,0,0,218, + 11,99,108,97,115,115,109,101,116,104,111,100,114,173,0,0, + 0,114,179,0,0,0,114,182,0,0,0,114,183,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,170,0,0,0,125,2,0,0,115,18,0, + 0,0,12,5,4,3,4,2,4,2,12,7,12,15,2,1, + 12,15,2,1,114,170,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,48, + 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, + 6,100,7,132,0,90,6,100,8,100,9,132,0,90,7,100, + 10,83,0,41,11,218,13,95,76,111,97,100,101,114,66,97, + 115,105,99,115,122,83,66,97,115,101,32,99,108,97,115,115, + 32,111,102,32,99,111,109,109,111,110,32,99,111,100,101,32, + 110,101,101,100,101,100,32,98,121,32,98,111,116,104,32,83, + 111,117,114,99,101,76,111,97,100,101,114,32,97,110,100,10, + 32,32,32,32,83,111,117,114,99,101,108,101,115,115,70,105, + 108,101,76,111,97,100,101,114,46,99,2,0,0,0,0,0, + 0,0,5,0,0,0,4,0,0,0,67,0,0,0,115,64, + 0,0,0,116,0,124,0,160,1,124,1,161,1,131,1,100, + 1,25,0,125,2,124,2,160,2,100,2,100,1,161,2,100, + 3,25,0,125,3,124,1,160,3,100,2,161,1,100,4,25, + 0,125,4,124,3,100,5,107,2,111,62,124,4,100,5,107, + 3,83,0,41,6,122,141,67,111,110,99,114,101,116,101,32, + 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111, + 102,32,73,110,115,112,101,99,116,76,111,97,100,101,114,46, + 105,115,95,112,97,99,107,97,103,101,32,98,121,32,99,104, + 101,99,107,105,110,103,32,105,102,10,32,32,32,32,32,32, + 32,32,116,104,101,32,112,97,116,104,32,114,101,116,117,114, + 110,101,100,32,98,121,32,103,101,116,95,102,105,108,101,110, + 97,109,101,32,104,97,115,32,97,32,102,105,108,101,110,97, + 109,101,32,111,102,32,39,95,95,105,110,105,116,95,95,46, + 112,121,39,46,114,29,0,0,0,114,59,0,0,0,114,60, + 0,0,0,114,57,0,0,0,218,8,95,95,105,110,105,116, + 95,95,41,4,114,38,0,0,0,114,159,0,0,0,114,34, + 0,0,0,114,32,0,0,0,41,5,114,102,0,0,0,114, + 121,0,0,0,114,96,0,0,0,90,13,102,105,108,101,110, + 97,109,101,95,98,97,115,101,90,9,116,97,105,108,95,110, 97,109,101,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,23,115,112,101,99,95,102,114,111,109,95,102,105, - 108,101,95,108,111,99,97,116,105,111,110,57,2,0,0,115, - 62,0,0,0,0,12,8,4,4,1,10,2,2,1,14,1, - 14,1,8,2,10,8,16,1,6,3,8,1,16,1,14,1, - 10,1,6,1,6,2,4,3,8,2,10,1,2,1,14,1, - 14,1,6,2,4,1,8,2,6,1,12,1,6,1,12,1, - 12,2,114,169,0,0,0,99,0,0,0,0,0,0,0,0, - 0,0,0,0,4,0,0,0,64,0,0,0,115,80,0,0, - 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,90, - 4,100,3,90,5,100,4,90,6,101,7,100,5,100,6,132, - 0,131,1,90,8,101,7,100,7,100,8,132,0,131,1,90, - 9,101,7,100,14,100,10,100,11,132,1,131,1,90,10,101, - 7,100,15,100,12,100,13,132,1,131,1,90,11,100,9,83, - 0,41,16,218,21,87,105,110,100,111,119,115,82,101,103,105, - 115,116,114,121,70,105,110,100,101,114,122,62,77,101,116,97, - 32,112,97,116,104,32,102,105,110,100,101,114,32,102,111,114, - 32,109,111,100,117,108,101,115,32,100,101,99,108,97,114,101, - 100,32,105,110,32,116,104,101,32,87,105,110,100,111,119,115, - 32,114,101,103,105,115,116,114,121,46,122,59,83,111,102,116, - 119,97,114,101,92,80,121,116,104,111,110,92,80,121,116,104, - 111,110,67,111,114,101,92,123,115,121,115,95,118,101,114,115, - 105,111,110,125,92,77,111,100,117,108,101,115,92,123,102,117, - 108,108,110,97,109,101,125,122,65,83,111,102,116,119,97,114, - 101,92,80,121,116,104,111,110,92,80,121,116,104,111,110,67, - 111,114,101,92,123,115,121,115,95,118,101,114,115,105,111,110, - 125,92,77,111,100,117,108,101,115,92,123,102,117,108,108,110, - 97,109,101,125,92,68,101,98,117,103,70,99,2,0,0,0, - 0,0,0,0,2,0,0,0,11,0,0,0,67,0,0,0, - 115,50,0,0,0,121,14,116,0,160,1,116,0,106,2,124, - 1,161,2,83,0,4,0,116,3,107,10,114,44,1,0,1, - 0,1,0,116,0,160,1,116,0,106,4,124,1,161,2,83, - 0,88,0,100,0,83,0,41,1,78,41,5,218,7,95,119, - 105,110,114,101,103,90,7,79,112,101,110,75,101,121,90,17, - 72,75,69,89,95,67,85,82,82,69,78,84,95,85,83,69, - 82,114,40,0,0,0,90,18,72,75,69,89,95,76,79,67, - 65,76,95,77,65,67,72,73,78,69,41,2,218,3,99,108, - 115,114,3,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,14,95,111,112,101,110,95,114,101,103, - 105,115,116,114,121,137,2,0,0,115,8,0,0,0,0,2, - 2,1,14,1,14,1,122,36,87,105,110,100,111,119,115,82, - 101,103,105,115,116,114,121,70,105,110,100,101,114,46,95,111, - 112,101,110,95,114,101,103,105,115,116,114,121,99,2,0,0, - 0,0,0,0,0,6,0,0,0,17,0,0,0,67,0,0, - 0,115,112,0,0,0,124,0,106,0,114,14,124,0,106,1, - 125,2,110,6,124,0,106,2,125,2,124,2,106,3,124,1, - 100,1,116,4,106,5,100,0,100,2,133,2,25,0,22,0, - 100,3,141,2,125,3,121,38,124,0,160,6,124,3,161,1, - 143,18,125,4,116,7,160,8,124,4,100,4,161,2,125,5, - 87,0,100,0,81,0,82,0,88,0,87,0,110,20,4,0, - 116,9,107,10,114,106,1,0,1,0,1,0,100,0,83,0, - 88,0,124,5,83,0,41,5,78,122,5,37,100,46,37,100, - 114,57,0,0,0,41,2,114,121,0,0,0,90,11,115,121, - 115,95,118,101,114,115,105,111,110,114,30,0,0,0,41,10, - 218,11,68,69,66,85,71,95,66,85,73,76,68,218,18,82, - 69,71,73,83,84,82,89,95,75,69,89,95,68,69,66,85, - 71,218,12,82,69,71,73,83,84,82,89,95,75,69,89,114, - 48,0,0,0,114,6,0,0,0,218,12,118,101,114,115,105, - 111,110,95,105,110,102,111,114,173,0,0,0,114,171,0,0, - 0,90,10,81,117,101,114,121,86,97,108,117,101,114,40,0, - 0,0,41,6,114,172,0,0,0,114,121,0,0,0,90,12, - 114,101,103,105,115,116,114,121,95,107,101,121,114,3,0,0, - 0,90,4,104,107,101,121,218,8,102,105,108,101,112,97,116, - 104,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,16,95,115,101,97,114,99,104,95,114,101,103,105,115,116, - 114,121,144,2,0,0,115,22,0,0,0,0,2,6,1,8, - 2,6,1,6,1,22,1,2,1,12,1,26,1,14,1,6, - 1,122,38,87,105,110,100,111,119,115,82,101,103,105,115,116, - 114,121,70,105,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, - 120,0,0,0,124,0,160,0,124,1,161,1,125,4,124,4, - 100,0,107,8,114,22,100,0,83,0,121,12,116,1,124,4, - 131,1,1,0,87,0,110,20,4,0,116,2,107,10,114,54, - 1,0,1,0,1,0,100,0,83,0,88,0,120,58,116,3, - 131,0,68,0,93,48,92,2,125,5,125,6,124,4,160,4, - 116,5,124,6,131,1,161,1,114,64,116,6,106,7,124,1, - 124,5,124,1,124,4,131,2,124,4,100,1,141,3,125,7, - 124,7,83,0,113,64,87,0,100,0,83,0,41,2,78,41, - 1,114,160,0,0,0,41,8,114,179,0,0,0,114,39,0, - 0,0,114,40,0,0,0,114,163,0,0,0,114,94,0,0, - 0,114,95,0,0,0,114,116,0,0,0,218,16,115,112,101, - 99,95,102,114,111,109,95,108,111,97,100,101,114,41,8,114, - 172,0,0,0,114,121,0,0,0,114,35,0,0,0,218,6, - 116,97,114,103,101,116,114,178,0,0,0,114,122,0,0,0, - 114,168,0,0,0,114,166,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,218,9,102,105,110,100,95, - 115,112,101,99,159,2,0,0,115,26,0,0,0,0,2,10, - 1,8,1,4,1,2,1,12,1,14,1,6,1,16,1,14, - 1,6,1,8,1,8,1,122,31,87,105,110,100,111,119,115, - 82,101,103,105,115,116,114,121,70,105,110,100,101,114,46,102, - 105,110,100,95,115,112,101,99,99,3,0,0,0,0,0,0, - 0,4,0,0,0,4,0,0,0,67,0,0,0,115,34,0, - 0,0,124,0,160,0,124,1,124,2,161,2,125,3,124,3, - 100,1,107,9,114,26,124,3,106,1,83,0,100,1,83,0, - 100,1,83,0,41,2,122,108,70,105,110,100,32,109,111,100, - 117,108,101,32,110,97,109,101,100,32,105,110,32,116,104,101, - 32,114,101,103,105,115,116,114,121,46,10,10,32,32,32,32, - 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, - 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, - 85,115,101,32,101,120,101,99,95,109,111,100,117,108,101,40, - 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 32,32,32,32,78,41,2,114,182,0,0,0,114,122,0,0, - 0,41,4,114,172,0,0,0,114,121,0,0,0,114,35,0, - 0,0,114,166,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,218,11,102,105,110,100,95,109,111,100, - 117,108,101,175,2,0,0,115,8,0,0,0,0,7,12,1, - 8,1,6,2,122,33,87,105,110,100,111,119,115,82,101,103, - 105,115,116,114,121,70,105,110,100,101,114,46,102,105,110,100, - 95,109,111,100,117,108,101,41,2,78,78,41,1,78,41,12, - 114,107,0,0,0,114,106,0,0,0,114,108,0,0,0,114, - 109,0,0,0,114,176,0,0,0,114,175,0,0,0,114,174, - 0,0,0,218,11,99,108,97,115,115,109,101,116,104,111,100, - 114,173,0,0,0,114,179,0,0,0,114,182,0,0,0,114, - 183,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,170,0,0,0,125,2,0, - 0,115,18,0,0,0,12,5,4,3,4,2,4,2,12,7, - 12,15,2,1,12,15,2,1,114,170,0,0,0,99,0,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, - 0,0,115,48,0,0,0,101,0,90,1,100,0,90,2,100, - 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, - 0,90,5,100,6,100,7,132,0,90,6,100,8,100,9,132, - 0,90,7,100,10,83,0,41,11,218,13,95,76,111,97,100, - 101,114,66,97,115,105,99,115,122,83,66,97,115,101,32,99, - 108,97,115,115,32,111,102,32,99,111,109,109,111,110,32,99, - 111,100,101,32,110,101,101,100,101,100,32,98,121,32,98,111, - 116,104,32,83,111,117,114,99,101,76,111,97,100,101,114,32, - 97,110,100,10,32,32,32,32,83,111,117,114,99,101,108,101, - 115,115,70,105,108,101,76,111,97,100,101,114,46,99,2,0, - 0,0,0,0,0,0,5,0,0,0,4,0,0,0,67,0, - 0,0,115,64,0,0,0,116,0,124,0,160,1,124,1,161, - 1,131,1,100,1,25,0,125,2,124,2,160,2,100,2,100, - 1,161,2,100,3,25,0,125,3,124,1,160,3,100,2,161, - 1,100,4,25,0,125,4,124,3,100,5,107,2,111,62,124, - 4,100,5,107,3,83,0,41,6,122,141,67,111,110,99,114, - 101,116,101,32,105,109,112,108,101,109,101,110,116,97,116,105, - 111,110,32,111,102,32,73,110,115,112,101,99,116,76,111,97, - 100,101,114,46,105,115,95,112,97,99,107,97,103,101,32,98, - 121,32,99,104,101,99,107,105,110,103,32,105,102,10,32,32, - 32,32,32,32,32,32,116,104,101,32,112,97,116,104,32,114, - 101,116,117,114,110,101,100,32,98,121,32,103,101,116,95,102, - 105,108,101,110,97,109,101,32,104,97,115,32,97,32,102,105, - 108,101,110,97,109,101,32,111,102,32,39,95,95,105,110,105, - 116,95,95,46,112,121,39,46,114,29,0,0,0,114,59,0, - 0,0,114,60,0,0,0,114,57,0,0,0,218,8,95,95, - 105,110,105,116,95,95,41,4,114,38,0,0,0,114,159,0, - 0,0,114,34,0,0,0,114,32,0,0,0,41,5,114,102, - 0,0,0,114,121,0,0,0,114,96,0,0,0,90,13,102, - 105,108,101,110,97,109,101,95,98,97,115,101,90,9,116,97, - 105,108,95,110,97,109,101,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,161,0,0,0,194,2,0,0,115, - 8,0,0,0,0,3,18,1,16,1,14,1,122,24,95,76, - 111,97,100,101,114,66,97,115,105,99,115,46,105,115,95,112, - 97,99,107,97,103,101,99,2,0,0,0,0,0,0,0,2, - 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, - 100,1,83,0,41,2,122,42,85,115,101,32,100,101,102,97, - 117,108,116,32,115,101,109,97,110,116,105,99,115,32,102,111, - 114,32,109,111,100,117,108,101,32,99,114,101,97,116,105,111, - 110,46,78,114,2,0,0,0,41,2,114,102,0,0,0,114, - 166,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,13,99,114,101,97,116,101,95,109,111,100,117, - 108,101,202,2,0,0,115,0,0,0,0,122,27,95,76,111, - 97,100,101,114,66,97,115,105,99,115,46,99,114,101,97,116, - 101,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, - 0,3,0,0,0,5,0,0,0,67,0,0,0,115,56,0, - 0,0,124,0,160,0,124,1,106,1,161,1,125,2,124,2, - 100,1,107,8,114,36,116,2,100,2,160,3,124,1,106,1, - 161,1,131,1,130,1,116,4,160,5,116,6,124,2,124,1, - 106,7,161,3,1,0,100,1,83,0,41,3,122,19,69,120, - 101,99,117,116,101,32,116,104,101,32,109,111,100,117,108,101, - 46,78,122,52,99,97,110,110,111,116,32,108,111,97,100,32, - 109,111,100,117,108,101,32,123,33,114,125,32,119,104,101,110, - 32,103,101,116,95,99,111,100,101,40,41,32,114,101,116,117, - 114,110,115,32,78,111,110,101,41,8,218,8,103,101,116,95, - 99,111,100,101,114,107,0,0,0,114,101,0,0,0,114,48, - 0,0,0,114,116,0,0,0,218,25,95,99,97,108,108,95, - 119,105,116,104,95,102,114,97,109,101,115,95,114,101,109,111, - 118,101,100,218,4,101,120,101,99,114,113,0,0,0,41,3, - 114,102,0,0,0,218,6,109,111,100,117,108,101,114,144,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,11,101,120,101,99,95,109,111,100,117,108,101,205,2, - 0,0,115,10,0,0,0,0,2,12,1,8,1,6,1,10, - 1,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, - 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,4,0,0,0,67,0,0, - 0,115,12,0,0,0,116,0,160,1,124,0,124,1,161,2, - 83,0,41,1,122,26,84,104,105,115,32,109,111,100,117,108, - 101,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 41,2,114,116,0,0,0,218,17,95,108,111,97,100,95,109, - 111,100,117,108,101,95,115,104,105,109,41,2,114,102,0,0, - 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,11,108,111,97,100,95,109,111,100,117, - 108,101,213,2,0,0,115,2,0,0,0,0,2,122,25,95, - 76,111,97,100,101,114,66,97,115,105,99,115,46,108,111,97, - 100,95,109,111,100,117,108,101,78,41,8,114,107,0,0,0, - 114,106,0,0,0,114,108,0,0,0,114,109,0,0,0,114, - 161,0,0,0,114,187,0,0,0,114,192,0,0,0,114,194, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,185,0,0,0,189,2,0,0, - 115,8,0,0,0,12,5,8,8,8,3,8,8,114,185,0, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,3, - 0,0,0,64,0,0,0,115,74,0,0,0,101,0,90,1, - 100,0,90,2,100,1,100,2,132,0,90,3,100,3,100,4, - 132,0,90,4,100,5,100,6,132,0,90,5,100,7,100,8, - 132,0,90,6,100,9,100,10,132,0,90,7,100,11,100,12, - 156,1,100,13,100,14,132,2,90,8,100,15,100,16,132,0, - 90,9,100,17,83,0,41,18,218,12,83,111,117,114,99,101, - 76,111,97,100,101,114,99,2,0,0,0,0,0,0,0,2, - 0,0,0,1,0,0,0,67,0,0,0,115,8,0,0,0, - 116,0,130,1,100,1,83,0,41,2,122,178,79,112,116,105, - 111,110,97,108,32,109,101,116,104,111,100,32,116,104,97,116, - 32,114,101,116,117,114,110,115,32,116,104,101,32,109,111,100, - 105,102,105,99,97,116,105,111,110,32,116,105,109,101,32,40, - 97,110,32,105,110,116,41,32,102,111,114,32,116,104,101,10, - 32,32,32,32,32,32,32,32,115,112,101,99,105,102,105,101, - 100,32,112,97,116,104,44,32,119,104,101,114,101,32,112,97, - 116,104,32,105,115,32,97,32,115,116,114,46,10,10,32,32, - 32,32,32,32,32,32,82,97,105,115,101,115,32,79,83,69, - 114,114,111,114,32,119,104,101,110,32,116,104,101,32,112,97, - 116,104,32,99,97,110,110,111,116,32,98,101,32,104,97,110, - 100,108,101,100,46,10,32,32,32,32,32,32,32,32,78,41, - 1,114,40,0,0,0,41,2,114,102,0,0,0,114,35,0, + 0,0,114,161,0,0,0,194,2,0,0,115,8,0,0,0, + 0,3,18,1,16,1,14,1,122,24,95,76,111,97,100,101, + 114,66,97,115,105,99,115,46,105,115,95,112,97,99,107,97, + 103,101,99,2,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,115,4,0,0,0,100,1,83,0, + 41,2,122,42,85,115,101,32,100,101,102,97,117,108,116,32, + 115,101,109,97,110,116,105,99,115,32,102,111,114,32,109,111, + 100,117,108,101,32,99,114,101,97,116,105,111,110,46,78,114, + 2,0,0,0,41,2,114,102,0,0,0,114,166,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 13,99,114,101,97,116,101,95,109,111,100,117,108,101,202,2, + 0,0,115,0,0,0,0,122,27,95,76,111,97,100,101,114, + 66,97,115,105,99,115,46,99,114,101,97,116,101,95,109,111, + 100,117,108,101,99,2,0,0,0,0,0,0,0,3,0,0, + 0,5,0,0,0,67,0,0,0,115,56,0,0,0,124,0, + 160,0,124,1,106,1,161,1,125,2,124,2,100,1,107,8, + 114,36,116,2,100,2,160,3,124,1,106,1,161,1,131,1, + 130,1,116,4,160,5,116,6,124,2,124,1,106,7,161,3, + 1,0,100,1,83,0,41,3,122,19,69,120,101,99,117,116, + 101,32,116,104,101,32,109,111,100,117,108,101,46,78,122,52, + 99,97,110,110,111,116,32,108,111,97,100,32,109,111,100,117, + 108,101,32,123,33,114,125,32,119,104,101,110,32,103,101,116, + 95,99,111,100,101,40,41,32,114,101,116,117,114,110,115,32, + 78,111,110,101,41,8,218,8,103,101,116,95,99,111,100,101, + 114,107,0,0,0,114,101,0,0,0,114,48,0,0,0,114, + 116,0,0,0,218,25,95,99,97,108,108,95,119,105,116,104, + 95,102,114,97,109,101,115,95,114,101,109,111,118,101,100,218, + 4,101,120,101,99,114,113,0,0,0,41,3,114,102,0,0, + 0,218,6,109,111,100,117,108,101,114,144,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,218,11,101, + 120,101,99,95,109,111,100,117,108,101,205,2,0,0,115,10, + 0,0,0,0,2,12,1,8,1,6,1,10,1,122,25,95, + 76,111,97,100,101,114,66,97,115,105,99,115,46,101,120,101, + 99,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,67,0,0,0,115,12,0, + 0,0,116,0,160,1,124,0,124,1,161,2,83,0,41,1, + 122,26,84,104,105,115,32,109,111,100,117,108,101,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,41,2,114,116, + 0,0,0,218,17,95,108,111,97,100,95,109,111,100,117,108, + 101,95,115,104,105,109,41,2,114,102,0,0,0,114,121,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,10,112,97,116,104,95,109,116,105,109,101,220,2,0, - 0,115,2,0,0,0,0,6,122,23,83,111,117,114,99,101, - 76,111,97,100,101,114,46,112,97,116,104,95,109,116,105,109, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,67,0,0,0,115,14,0,0,0,100,1,124,0,160, - 0,124,1,161,1,105,1,83,0,41,2,97,170,1,0,0, - 79,112,116,105,111,110,97,108,32,109,101,116,104,111,100,32, - 114,101,116,117,114,110,105,110,103,32,97,32,109,101,116,97, - 100,97,116,97,32,100,105,99,116,32,102,111,114,32,116,104, - 101,32,115,112,101,99,105,102,105,101,100,32,112,97,116,104, - 10,32,32,32,32,32,32,32,32,116,111,32,98,121,32,116, - 104,101,32,112,97,116,104,32,40,115,116,114,41,46,10,32, - 32,32,32,32,32,32,32,80,111,115,115,105,98,108,101,32, - 107,101,121,115,58,10,32,32,32,32,32,32,32,32,45,32, - 39,109,116,105,109,101,39,32,40,109,97,110,100,97,116,111, - 114,121,41,32,105,115,32,116,104,101,32,110,117,109,101,114, - 105,99,32,116,105,109,101,115,116,97,109,112,32,111,102,32, - 108,97,115,116,32,115,111,117,114,99,101,10,32,32,32,32, - 32,32,32,32,32,32,99,111,100,101,32,109,111,100,105,102, - 105,99,97,116,105,111,110,59,10,32,32,32,32,32,32,32, - 32,45,32,39,115,105,122,101,39,32,40,111,112,116,105,111, - 110,97,108,41,32,105,115,32,116,104,101,32,115,105,122,101, - 32,105,110,32,98,121,116,101,115,32,111,102,32,116,104,101, - 32,115,111,117,114,99,101,32,99,111,100,101,46,10,10,32, - 32,32,32,32,32,32,32,73,109,112,108,101,109,101,110,116, - 105,110,103,32,116,104,105,115,32,109,101,116,104,111,100,32, - 97,108,108,111,119,115,32,116,104,101,32,108,111,97,100,101, - 114,32,116,111,32,114,101,97,100,32,98,121,116,101,99,111, - 100,101,32,102,105,108,101,115,46,10,32,32,32,32,32,32, + 0,218,11,108,111,97,100,95,109,111,100,117,108,101,213,2, + 0,0,115,2,0,0,0,0,2,122,25,95,76,111,97,100, + 101,114,66,97,115,105,99,115,46,108,111,97,100,95,109,111, + 100,117,108,101,78,41,8,114,107,0,0,0,114,106,0,0, + 0,114,108,0,0,0,114,109,0,0,0,114,161,0,0,0, + 114,187,0,0,0,114,192,0,0,0,114,194,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,185,0,0,0,189,2,0,0,115,8,0,0, + 0,12,5,8,8,8,3,8,8,114,185,0,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, + 0,0,0,115,74,0,0,0,101,0,90,1,100,0,90,2, + 100,1,100,2,132,0,90,3,100,3,100,4,132,0,90,4, + 100,5,100,6,132,0,90,5,100,7,100,8,132,0,90,6, + 100,9,100,10,132,0,90,7,100,11,100,12,156,1,100,13, + 100,14,132,2,90,8,100,15,100,16,132,0,90,9,100,17, + 83,0,41,18,218,12,83,111,117,114,99,101,76,111,97,100, + 101,114,99,2,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,115,8,0,0,0,116,0,130,1, + 100,1,83,0,41,2,122,178,79,112,116,105,111,110,97,108, + 32,109,101,116,104,111,100,32,116,104,97,116,32,114,101,116, + 117,114,110,115,32,116,104,101,32,109,111,100,105,102,105,99, + 97,116,105,111,110,32,116,105,109,101,32,40,97,110,32,105, + 110,116,41,32,102,111,114,32,116,104,101,10,32,32,32,32, + 32,32,32,32,115,112,101,99,105,102,105,101,100,32,112,97, + 116,104,44,32,119,104,101,114,101,32,112,97,116,104,32,105, + 115,32,97,32,115,116,114,46,10,10,32,32,32,32,32,32, 32,32,82,97,105,115,101,115,32,79,83,69,114,114,111,114, 32,119,104,101,110,32,116,104,101,32,112,97,116,104,32,99, 97,110,110,111,116,32,98,101,32,104,97,110,100,108,101,100, - 46,10,32,32,32,32,32,32,32,32,114,149,0,0,0,41, - 1,114,196,0,0,0,41,2,114,102,0,0,0,114,35,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,10,112,97,116,104,95,115,116,97,116,115,228,2,0, - 0,115,2,0,0,0,0,11,122,23,83,111,117,114,99,101, - 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, - 115,99,4,0,0,0,0,0,0,0,4,0,0,0,4,0, - 0,0,67,0,0,0,115,12,0,0,0,124,0,160,0,124, - 2,124,3,161,2,83,0,41,1,122,228,79,112,116,105,111, - 110,97,108,32,109,101,116,104,111,100,32,119,104,105,99,104, - 32,119,114,105,116,101,115,32,100,97,116,97,32,40,98,121, - 116,101,115,41,32,116,111,32,97,32,102,105,108,101,32,112, - 97,116,104,32,40,97,32,115,116,114,41,46,10,10,32,32, - 32,32,32,32,32,32,73,109,112,108,101,109,101,110,116,105, - 110,103,32,116,104,105,115,32,109,101,116,104,111,100,32,97, - 108,108,111,119,115,32,102,111,114,32,116,104,101,32,119,114, - 105,116,105,110,103,32,111,102,32,98,121,116,101,99,111,100, - 101,32,102,105,108,101,115,46,10,10,32,32,32,32,32,32, - 32,32,84,104,101,32,115,111,117,114,99,101,32,112,97,116, - 104,32,105,115,32,110,101,101,100,101,100,32,105,110,32,111, - 114,100,101,114,32,116,111,32,99,111,114,114,101,99,116,108, - 121,32,116,114,97,110,115,102,101,114,32,112,101,114,109,105, - 115,115,105,111,110,115,10,32,32,32,32,32,32,32,32,41, - 1,218,8,115,101,116,95,100,97,116,97,41,4,114,102,0, - 0,0,114,92,0,0,0,90,10,99,97,99,104,101,95,112, - 97,116,104,114,54,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,15,95,99,97,99,104,101,95, - 98,121,116,101,99,111,100,101,241,2,0,0,115,2,0,0, - 0,0,8,122,28,83,111,117,114,99,101,76,111,97,100,101, - 114,46,95,99,97,99,104,101,95,98,121,116,101,99,111,100, - 101,99,3,0,0,0,0,0,0,0,3,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,122,150,79,112,116,105,111,110,97,108,32,109,101,116,104, - 111,100,32,119,104,105,99,104,32,119,114,105,116,101,115,32, - 100,97,116,97,32,40,98,121,116,101,115,41,32,116,111,32, - 97,32,102,105,108,101,32,112,97,116,104,32,40,97,32,115, - 116,114,41,46,10,10,32,32,32,32,32,32,32,32,73,109, - 112,108,101,109,101,110,116,105,110,103,32,116,104,105,115,32, - 109,101,116,104,111,100,32,97,108,108,111,119,115,32,102,111, - 114,32,116,104,101,32,119,114,105,116,105,110,103,32,111,102, - 32,98,121,116,101,99,111,100,101,32,102,105,108,101,115,46, - 10,32,32,32,32,32,32,32,32,78,114,2,0,0,0,41, - 3,114,102,0,0,0,114,35,0,0,0,114,54,0,0,0, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 198,0,0,0,251,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,82,0,0,0,124,0, - 160,0,124,1,161,1,125,2,121,14,124,0,160,1,124,2, - 161,1,125,3,87,0,110,48,4,0,116,2,107,10,114,72, - 1,0,125,4,1,0,122,20,116,3,100,1,124,1,100,2, - 141,2,124,4,130,2,87,0,89,0,100,3,100,3,125,4, - 126,4,88,0,110,2,88,0,116,4,124,3,131,1,83,0, - 41,4,122,52,67,111,110,99,114,101,116,101,32,105,109,112, - 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,73, - 110,115,112,101,99,116,76,111,97,100,101,114,46,103,101,116, - 95,115,111,117,114,99,101,46,122,39,115,111,117,114,99,101, - 32,110,111,116,32,97,118,97,105,108,97,98,108,101,32,116, - 104,114,111,117,103,104,32,103,101,116,95,100,97,116,97,40, - 41,41,1,114,100,0,0,0,78,41,5,114,159,0,0,0, - 218,8,103,101,116,95,100,97,116,97,114,40,0,0,0,114, - 101,0,0,0,114,157,0,0,0,41,5,114,102,0,0,0, - 114,121,0,0,0,114,35,0,0,0,114,155,0,0,0,218, - 3,101,120,99,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,10,103,101,116,95,115,111,117,114,99,101,2, - 3,0,0,115,14,0,0,0,0,2,10,1,2,1,14,1, - 16,1,4,1,28,1,122,23,83,111,117,114,99,101,76,111, - 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,114, - 89,0,0,0,41,1,218,9,95,111,112,116,105,109,105,122, - 101,99,3,0,0,0,1,0,0,0,4,0,0,0,8,0, - 0,0,67,0,0,0,115,22,0,0,0,116,0,106,1,116, - 2,124,1,124,2,100,1,100,2,124,3,100,3,141,6,83, - 0,41,4,122,130,82,101,116,117,114,110,32,116,104,101,32, - 99,111,100,101,32,111,98,106,101,99,116,32,99,111,109,112, - 105,108,101,100,32,102,114,111,109,32,115,111,117,114,99,101, - 46,10,10,32,32,32,32,32,32,32,32,84,104,101,32,39, - 100,97,116,97,39,32,97,114,103,117,109,101,110,116,32,99, - 97,110,32,98,101,32,97,110,121,32,111,98,106,101,99,116, - 32,116,121,112,101,32,116,104,97,116,32,99,111,109,112,105, - 108,101,40,41,32,115,117,112,112,111,114,116,115,46,10,32, - 32,32,32,32,32,32,32,114,190,0,0,0,84,41,2,218, - 12,100,111,110,116,95,105,110,104,101,114,105,116,114,70,0, - 0,0,41,3,114,116,0,0,0,114,189,0,0,0,218,7, - 99,111,109,112,105,108,101,41,4,114,102,0,0,0,114,54, - 0,0,0,114,35,0,0,0,114,203,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,218,14,115,111, - 117,114,99,101,95,116,111,95,99,111,100,101,12,3,0,0, - 115,4,0,0,0,0,5,12,1,122,27,83,111,117,114,99, - 101,76,111,97,100,101,114,46,115,111,117,114,99,101,95,116, - 111,95,99,111,100,101,99,2,0,0,0,0,0,0,0,15, - 0,0,0,43,0,0,0,67,0,0,0,115,46,2,0,0, - 124,0,160,0,124,1,161,1,125,2,100,1,125,3,100,1, - 125,4,100,1,125,5,100,2,125,6,100,3,125,7,121,12, - 116,1,124,2,131,1,125,8,87,0,110,26,4,0,116,2, - 107,10,114,68,1,0,1,0,1,0,100,1,125,8,89,0, - 144,1,110,48,88,0,121,14,124,0,160,3,124,2,161,1, - 125,9,87,0,110,22,4,0,116,4,107,10,114,106,1,0, - 1,0,1,0,89,0,144,1,110,10,88,0,116,5,124,9, - 100,4,25,0,131,1,125,3,121,14,124,0,160,6,124,8, - 161,1,125,10,87,0,110,20,4,0,116,4,107,10,114,154, - 1,0,1,0,1,0,89,0,110,218,88,0,124,1,124,8, - 100,5,156,2,125,11,121,148,116,7,124,10,124,1,124,11, - 131,3,125,12,116,8,124,10,131,1,100,6,100,1,133,2, - 25,0,125,13,124,12,100,7,64,0,100,8,107,3,125,6, - 124,6,144,1,114,36,124,12,100,9,64,0,100,8,107,3, - 125,7,116,9,106,10,100,10,107,3,144,1,114,56,124,7, - 115,254,116,9,106,10,100,11,107,2,144,1,114,56,124,0, - 160,6,124,2,161,1,125,4,116,9,160,11,116,12,124,4, - 161,2,125,5,116,13,124,10,124,5,124,1,124,11,131,4, - 1,0,110,20,116,14,124,10,124,3,124,9,100,12,25,0, - 124,1,124,11,131,5,1,0,87,0,110,26,4,0,116,15, - 116,16,102,2,107,10,144,1,114,84,1,0,1,0,1,0, - 89,0,110,32,88,0,116,17,160,18,100,13,124,8,124,2, - 161,3,1,0,116,19,124,13,124,1,124,8,124,2,100,14, - 141,4,83,0,124,4,100,1,107,8,144,1,114,136,124,0, - 160,6,124,2,161,1,125,4,124,0,160,20,124,4,124,2, - 161,2,125,14,116,17,160,18,100,15,124,2,161,2,1,0, - 116,21,106,22,144,2,115,42,124,8,100,1,107,9,144,2, - 114,42,124,3,100,1,107,9,144,2,114,42,124,6,144,1, - 114,228,124,5,100,1,107,8,144,1,114,214,116,9,160,11, - 124,4,161,1,125,5,116,23,124,14,124,5,124,7,131,3, - 125,10,110,16,116,24,124,14,124,3,116,25,124,4,131,1, - 131,3,125,10,121,30,124,0,160,26,124,2,124,8,124,10, - 161,3,1,0,116,17,160,18,100,16,124,8,161,2,1,0, - 87,0,110,22,4,0,116,2,107,10,144,2,114,40,1,0, - 1,0,1,0,89,0,110,2,88,0,124,14,83,0,41,17, - 122,190,67,111,110,99,114,101,116,101,32,105,109,112,108,101, - 109,101,110,116,97,116,105,111,110,32,111,102,32,73,110,115, - 112,101,99,116,76,111,97,100,101,114,46,103,101,116,95,99, - 111,100,101,46,10,10,32,32,32,32,32,32,32,32,82,101, - 97,100,105,110,103,32,111,102,32,98,121,116,101,99,111,100, - 101,32,114,101,113,117,105,114,101,115,32,112,97,116,104,95, - 115,116,97,116,115,32,116,111,32,98,101,32,105,109,112,108, - 101,109,101,110,116,101,100,46,32,84,111,32,119,114,105,116, - 101,10,32,32,32,32,32,32,32,32,98,121,116,101,99,111, - 100,101,44,32,115,101,116,95,100,97,116,97,32,109,117,115, - 116,32,97,108,115,111,32,98,101,32,105,109,112,108,101,109, - 101,110,116,101,100,46,10,10,32,32,32,32,32,32,32,32, - 78,70,84,114,149,0,0,0,41,2,114,100,0,0,0,114, - 35,0,0,0,114,126,0,0,0,114,29,0,0,0,114,60, - 0,0,0,114,57,0,0,0,90,5,110,101,118,101,114,90, - 6,97,108,119,97,121,115,218,4,115,105,122,101,122,13,123, - 125,32,109,97,116,99,104,101,115,32,123,125,41,3,114,100, - 0,0,0,114,91,0,0,0,114,92,0,0,0,122,19,99, - 111,100,101,32,111,98,106,101,99,116,32,102,114,111,109,32, - 123,125,122,10,119,114,111,116,101,32,123,33,114,125,41,27, - 114,159,0,0,0,114,81,0,0,0,114,68,0,0,0,114, - 197,0,0,0,114,40,0,0,0,114,14,0,0,0,114,200, - 0,0,0,114,133,0,0,0,218,10,109,101,109,111,114,121, - 118,105,101,119,114,143,0,0,0,90,21,99,104,101,99,107, - 95,104,97,115,104,95,98,97,115,101,100,95,112,121,99,115, - 114,138,0,0,0,218,17,95,82,65,87,95,77,65,71,73, - 67,95,78,85,77,66,69,82,114,139,0,0,0,114,137,0, - 0,0,114,101,0,0,0,114,131,0,0,0,114,116,0,0, - 0,114,130,0,0,0,114,145,0,0,0,114,206,0,0,0, - 114,6,0,0,0,218,19,100,111,110,116,95,119,114,105,116, - 101,95,98,121,116,101,99,111,100,101,114,152,0,0,0,114, - 150,0,0,0,114,31,0,0,0,114,199,0,0,0,41,15, - 114,102,0,0,0,114,121,0,0,0,114,92,0,0,0,114, - 135,0,0,0,114,155,0,0,0,114,138,0,0,0,90,10, - 104,97,115,104,95,98,97,115,101,100,90,12,99,104,101,99, - 107,95,115,111,117,114,99,101,114,91,0,0,0,218,2,115, - 116,114,54,0,0,0,114,132,0,0,0,114,69,0,0,0, - 90,10,98,121,116,101,115,95,100,97,116,97,90,11,99,111, - 100,101,95,111,98,106,101,99,116,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,188,0,0,0,20,3,0, - 0,115,134,0,0,0,0,7,10,1,4,1,4,1,4,1, - 4,1,4,1,2,1,12,1,14,1,12,2,2,1,14,1, - 14,1,8,2,12,1,2,1,14,1,14,1,6,3,2,1, - 8,2,2,1,12,1,16,1,12,1,6,1,12,1,12,1, - 4,1,12,1,10,1,4,1,2,1,6,2,8,1,8,2, - 2,1,2,1,2,1,6,1,2,1,10,2,20,1,6,2, - 8,1,6,1,6,1,2,1,8,1,10,1,10,1,12,1, - 12,1,18,1,10,1,6,1,10,1,10,1,14,2,6,1, - 10,1,2,1,14,1,16,1,16,1,6,1,122,21,83,111, - 117,114,99,101,76,111,97,100,101,114,46,103,101,116,95,99, - 111,100,101,78,41,10,114,107,0,0,0,114,106,0,0,0, - 114,108,0,0,0,114,196,0,0,0,114,197,0,0,0,114, - 199,0,0,0,114,198,0,0,0,114,202,0,0,0,114,206, - 0,0,0,114,188,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,195,0,0, - 0,218,2,0,0,115,14,0,0,0,8,2,8,8,8,13, - 8,10,8,7,8,10,14,8,114,195,0,0,0,99,0,0, - 0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, - 0,0,115,80,0,0,0,101,0,90,1,100,0,90,2,100, - 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, - 0,90,5,100,6,100,7,132,0,90,6,101,7,135,0,102, - 1,100,8,100,9,132,8,131,1,90,8,101,7,100,10,100, - 11,132,0,131,1,90,9,100,12,100,13,132,0,90,10,135, - 0,4,0,90,11,83,0,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,16,0,0,0,124,1,124,0,95,0,124,2, - 124,0,95,1,100,1,83,0,41,2,122,75,67,97,99,104, - 101,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109, - 101,32,97,110,100,32,116,104,101,32,112,97,116,104,32,116, - 111,32,116,104,101,32,102,105,108,101,32,102,111,117,110,100, - 32,98,121,32,116,104,101,10,32,32,32,32,32,32,32,32, - 102,105,110,100,101,114,46,78,41,2,114,100,0,0,0,114, - 35,0,0,0,41,3,114,102,0,0,0,114,121,0,0,0, - 114,35,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,186,0,0,0,111,3,0,0,115,4,0, - 0,0,0,3,6,1,122,19,70,105,108,101,76,111,97,100, - 101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 115,24,0,0,0,124,0,106,0,124,1,106,0,107,2,111, - 22,124,0,106,1,124,1,106,1,107,2,83,0,41,1,78, - 41,2,218,9,95,95,99,108,97,115,115,95,95,114,113,0, - 0,0,41,2,114,102,0,0,0,218,5,111,116,104,101,114, + 46,10,32,32,32,32,32,32,32,32,78,41,1,114,40,0, + 0,0,41,2,114,102,0,0,0,114,35,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,218,10,112, + 97,116,104,95,109,116,105,109,101,220,2,0,0,115,2,0, + 0,0,0,6,122,23,83,111,117,114,99,101,76,111,97,100, + 101,114,46,112,97,116,104,95,109,116,105,109,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,67,0, + 0,0,115,14,0,0,0,100,1,124,0,160,0,124,1,161, + 1,105,1,83,0,41,2,97,170,1,0,0,79,112,116,105, + 111,110,97,108,32,109,101,116,104,111,100,32,114,101,116,117, + 114,110,105,110,103,32,97,32,109,101,116,97,100,97,116,97, + 32,100,105,99,116,32,102,111,114,32,116,104,101,32,115,112, + 101,99,105,102,105,101,100,32,112,97,116,104,10,32,32,32, + 32,32,32,32,32,116,111,32,98,121,32,116,104,101,32,112, + 97,116,104,32,40,115,116,114,41,46,10,32,32,32,32,32, + 32,32,32,80,111,115,115,105,98,108,101,32,107,101,121,115, + 58,10,32,32,32,32,32,32,32,32,45,32,39,109,116,105, + 109,101,39,32,40,109,97,110,100,97,116,111,114,121,41,32, + 105,115,32,116,104,101,32,110,117,109,101,114,105,99,32,116, + 105,109,101,115,116,97,109,112,32,111,102,32,108,97,115,116, + 32,115,111,117,114,99,101,10,32,32,32,32,32,32,32,32, + 32,32,99,111,100,101,32,109,111,100,105,102,105,99,97,116, + 105,111,110,59,10,32,32,32,32,32,32,32,32,45,32,39, + 115,105,122,101,39,32,40,111,112,116,105,111,110,97,108,41, + 32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32, + 98,121,116,101,115,32,111,102,32,116,104,101,32,115,111,117, + 114,99,101,32,99,111,100,101,46,10,10,32,32,32,32,32, + 32,32,32,73,109,112,108,101,109,101,110,116,105,110,103,32, + 116,104,105,115,32,109,101,116,104,111,100,32,97,108,108,111, + 119,115,32,116,104,101,32,108,111,97,100,101,114,32,116,111, + 32,114,101,97,100,32,98,121,116,101,99,111,100,101,32,102, + 105,108,101,115,46,10,32,32,32,32,32,32,32,32,82,97, + 105,115,101,115,32,79,83,69,114,114,111,114,32,119,104,101, + 110,32,116,104,101,32,112,97,116,104,32,99,97,110,110,111, + 116,32,98,101,32,104,97,110,100,108,101,100,46,10,32,32, + 32,32,32,32,32,32,114,149,0,0,0,41,1,114,196,0, + 0,0,41,2,114,102,0,0,0,114,35,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,218,10,112, + 97,116,104,95,115,116,97,116,115,228,2,0,0,115,2,0, + 0,0,0,11,122,23,83,111,117,114,99,101,76,111,97,100, + 101,114,46,112,97,116,104,95,115,116,97,116,115,99,4,0, + 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, + 0,0,115,12,0,0,0,124,0,160,0,124,2,124,3,161, + 2,83,0,41,1,122,228,79,112,116,105,111,110,97,108,32, + 109,101,116,104,111,100,32,119,104,105,99,104,32,119,114,105, + 116,101,115,32,100,97,116,97,32,40,98,121,116,101,115,41, + 32,116,111,32,97,32,102,105,108,101,32,112,97,116,104,32, + 40,97,32,115,116,114,41,46,10,10,32,32,32,32,32,32, + 32,32,73,109,112,108,101,109,101,110,116,105,110,103,32,116, + 104,105,115,32,109,101,116,104,111,100,32,97,108,108,111,119, + 115,32,102,111,114,32,116,104,101,32,119,114,105,116,105,110, + 103,32,111,102,32,98,121,116,101,99,111,100,101,32,102,105, + 108,101,115,46,10,10,32,32,32,32,32,32,32,32,84,104, + 101,32,115,111,117,114,99,101,32,112,97,116,104,32,105,115, + 32,110,101,101,100,101,100,32,105,110,32,111,114,100,101,114, + 32,116,111,32,99,111,114,114,101,99,116,108,121,32,116,114, + 97,110,115,102,101,114,32,112,101,114,109,105,115,115,105,111, + 110,115,10,32,32,32,32,32,32,32,32,41,1,218,8,115, + 101,116,95,100,97,116,97,41,4,114,102,0,0,0,114,92, + 0,0,0,90,10,99,97,99,104,101,95,112,97,116,104,114, + 54,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,218,15,95,99,97,99,104,101,95,98,121,116,101, + 99,111,100,101,241,2,0,0,115,2,0,0,0,0,8,122, + 28,83,111,117,114,99,101,76,111,97,100,101,114,46,95,99, + 97,99,104,101,95,98,121,116,101,99,111,100,101,99,3,0, + 0,0,0,0,0,0,3,0,0,0,1,0,0,0,67,0, + 0,0,115,4,0,0,0,100,1,83,0,41,2,122,150,79, + 112,116,105,111,110,97,108,32,109,101,116,104,111,100,32,119, + 104,105,99,104,32,119,114,105,116,101,115,32,100,97,116,97, + 32,40,98,121,116,101,115,41,32,116,111,32,97,32,102,105, + 108,101,32,112,97,116,104,32,40,97,32,115,116,114,41,46, + 10,10,32,32,32,32,32,32,32,32,73,109,112,108,101,109, + 101,110,116,105,110,103,32,116,104,105,115,32,109,101,116,104, + 111,100,32,97,108,108,111,119,115,32,102,111,114,32,116,104, + 101,32,119,114,105,116,105,110,103,32,111,102,32,98,121,116, + 101,99,111,100,101,32,102,105,108,101,115,46,10,32,32,32, + 32,32,32,32,32,78,114,2,0,0,0,41,3,114,102,0, + 0,0,114,35,0,0,0,114,54,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,198,0,0,0, + 251,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,82,0,0,0,124,0,160,0,124,1, + 161,1,125,2,121,14,124,0,160,1,124,2,161,1,125,3, + 87,0,110,48,4,0,116,2,107,10,114,72,1,0,125,4, + 1,0,122,20,116,3,100,1,124,1,100,2,141,2,124,4, + 130,2,87,0,89,0,100,3,100,3,125,4,126,4,88,0, + 110,2,88,0,116,4,124,3,131,1,83,0,41,4,122,52, + 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, + 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, + 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, + 103,104,32,103,101,116,95,100,97,116,97,40,41,41,1,114, + 100,0,0,0,78,41,5,114,159,0,0,0,218,8,103,101, + 116,95,100,97,116,97,114,40,0,0,0,114,101,0,0,0, + 114,157,0,0,0,41,5,114,102,0,0,0,114,121,0,0, + 0,114,35,0,0,0,114,155,0,0,0,218,3,101,120,99, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 6,95,95,101,113,95,95,117,3,0,0,115,4,0,0,0, - 0,1,12,1,122,17,70,105,108,101,76,111,97,100,101,114, - 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0, - 0,116,0,124,0,106,1,131,1,116,0,124,0,106,2,131, - 1,65,0,83,0,41,1,78,41,3,218,4,104,97,115,104, - 114,100,0,0,0,114,35,0,0,0,41,1,114,102,0,0, + 10,103,101,116,95,115,111,117,114,99,101,2,3,0,0,115, + 14,0,0,0,0,2,10,1,2,1,14,1,16,1,4,1, + 28,1,122,23,83,111,117,114,99,101,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,114,89,0,0,0, + 41,1,218,9,95,111,112,116,105,109,105,122,101,99,3,0, + 0,0,1,0,0,0,4,0,0,0,8,0,0,0,67,0, + 0,0,115,22,0,0,0,116,0,106,1,116,2,124,1,124, + 2,100,1,100,2,124,3,100,3,141,6,83,0,41,4,122, + 130,82,101,116,117,114,110,32,116,104,101,32,99,111,100,101, + 32,111,98,106,101,99,116,32,99,111,109,112,105,108,101,100, + 32,102,114,111,109,32,115,111,117,114,99,101,46,10,10,32, + 32,32,32,32,32,32,32,84,104,101,32,39,100,97,116,97, + 39,32,97,114,103,117,109,101,110,116,32,99,97,110,32,98, + 101,32,97,110,121,32,111,98,106,101,99,116,32,116,121,112, + 101,32,116,104,97,116,32,99,111,109,112,105,108,101,40,41, + 32,115,117,112,112,111,114,116,115,46,10,32,32,32,32,32, + 32,32,32,114,190,0,0,0,84,41,2,218,12,100,111,110, + 116,95,105,110,104,101,114,105,116,114,70,0,0,0,41,3, + 114,116,0,0,0,114,189,0,0,0,218,7,99,111,109,112, + 105,108,101,41,4,114,102,0,0,0,114,54,0,0,0,114, + 35,0,0,0,114,203,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,218,14,115,111,117,114,99,101, + 95,116,111,95,99,111,100,101,12,3,0,0,115,4,0,0, + 0,0,5,12,1,122,27,83,111,117,114,99,101,76,111,97, + 100,101,114,46,115,111,117,114,99,101,95,116,111,95,99,111, + 100,101,99,2,0,0,0,0,0,0,0,15,0,0,0,43, + 0,0,0,67,0,0,0,115,46,2,0,0,124,0,160,0, + 124,1,161,1,125,2,100,1,125,3,100,1,125,4,100,1, + 125,5,100,2,125,6,100,3,125,7,121,12,116,1,124,2, + 131,1,125,8,87,0,110,26,4,0,116,2,107,10,114,68, + 1,0,1,0,1,0,100,1,125,8,89,0,144,1,110,48, + 88,0,121,14,124,0,160,3,124,2,161,1,125,9,87,0, + 110,22,4,0,116,4,107,10,114,106,1,0,1,0,1,0, + 89,0,144,1,110,10,88,0,116,5,124,9,100,4,25,0, + 131,1,125,3,121,14,124,0,160,6,124,8,161,1,125,10, + 87,0,110,20,4,0,116,4,107,10,114,154,1,0,1,0, + 1,0,89,0,110,218,88,0,124,1,124,8,100,5,156,2, + 125,11,121,148,116,7,124,10,124,1,124,11,131,3,125,12, + 116,8,124,10,131,1,100,6,100,1,133,2,25,0,125,13, + 124,12,100,7,64,0,100,8,107,3,125,6,124,6,144,1, + 114,36,124,12,100,9,64,0,100,8,107,3,125,7,116,9, + 106,10,100,10,107,3,144,1,114,56,124,7,115,254,116,9, + 106,10,100,11,107,2,144,1,114,56,124,0,160,6,124,2, + 161,1,125,4,116,9,160,11,116,12,124,4,161,2,125,5, + 116,13,124,10,124,5,124,1,124,11,131,4,1,0,110,20, + 116,14,124,10,124,3,124,9,100,12,25,0,124,1,124,11, + 131,5,1,0,87,0,110,26,4,0,116,15,116,16,102,2, + 107,10,144,1,114,84,1,0,1,0,1,0,89,0,110,32, + 88,0,116,17,160,18,100,13,124,8,124,2,161,3,1,0, + 116,19,124,13,124,1,124,8,124,2,100,14,141,4,83,0, + 124,4,100,1,107,8,144,1,114,136,124,0,160,6,124,2, + 161,1,125,4,124,0,160,20,124,4,124,2,161,2,125,14, + 116,17,160,18,100,15,124,2,161,2,1,0,116,21,106,22, + 144,2,115,42,124,8,100,1,107,9,144,2,114,42,124,3, + 100,1,107,9,144,2,114,42,124,6,144,1,114,228,124,5, + 100,1,107,8,144,1,114,214,116,9,160,11,124,4,161,1, + 125,5,116,23,124,14,124,5,124,7,131,3,125,10,110,16, + 116,24,124,14,124,3,116,25,124,4,131,1,131,3,125,10, + 121,30,124,0,160,26,124,2,124,8,124,10,161,3,1,0, + 116,17,160,18,100,16,124,8,161,2,1,0,87,0,110,22, + 4,0,116,2,107,10,144,2,114,40,1,0,1,0,1,0, + 89,0,110,2,88,0,124,14,83,0,41,17,122,190,67,111, + 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,32,111,102,32,73,110,115,112,101,99,116, + 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,46, + 10,10,32,32,32,32,32,32,32,32,82,101,97,100,105,110, + 103,32,111,102,32,98,121,116,101,99,111,100,101,32,114,101, + 113,117,105,114,101,115,32,112,97,116,104,95,115,116,97,116, + 115,32,116,111,32,98,101,32,105,109,112,108,101,109,101,110, + 116,101,100,46,32,84,111,32,119,114,105,116,101,10,32,32, + 32,32,32,32,32,32,98,121,116,101,99,111,100,101,44,32, + 115,101,116,95,100,97,116,97,32,109,117,115,116,32,97,108, + 115,111,32,98,101,32,105,109,112,108,101,109,101,110,116,101, + 100,46,10,10,32,32,32,32,32,32,32,32,78,70,84,114, + 149,0,0,0,41,2,114,100,0,0,0,114,35,0,0,0, + 114,126,0,0,0,114,29,0,0,0,114,60,0,0,0,114, + 57,0,0,0,90,5,110,101,118,101,114,90,6,97,108,119, + 97,121,115,218,4,115,105,122,101,122,13,123,125,32,109,97, + 116,99,104,101,115,32,123,125,41,3,114,100,0,0,0,114, + 91,0,0,0,114,92,0,0,0,122,19,99,111,100,101,32, + 111,98,106,101,99,116,32,102,114,111,109,32,123,125,122,10, + 119,114,111,116,101,32,123,33,114,125,41,27,114,159,0,0, + 0,114,81,0,0,0,114,68,0,0,0,114,197,0,0,0, + 114,40,0,0,0,114,14,0,0,0,114,200,0,0,0,114, + 133,0,0,0,218,10,109,101,109,111,114,121,118,105,101,119, + 114,143,0,0,0,90,21,99,104,101,99,107,95,104,97,115, + 104,95,98,97,115,101,100,95,112,121,99,115,114,138,0,0, + 0,218,17,95,82,65,87,95,77,65,71,73,67,95,78,85, + 77,66,69,82,114,139,0,0,0,114,137,0,0,0,114,101, + 0,0,0,114,131,0,0,0,114,116,0,0,0,114,130,0, + 0,0,114,145,0,0,0,114,206,0,0,0,114,6,0,0, + 0,218,19,100,111,110,116,95,119,114,105,116,101,95,98,121, + 116,101,99,111,100,101,114,152,0,0,0,114,150,0,0,0, + 114,31,0,0,0,114,199,0,0,0,41,15,114,102,0,0, + 0,114,121,0,0,0,114,92,0,0,0,114,135,0,0,0, + 114,155,0,0,0,114,138,0,0,0,90,10,104,97,115,104, + 95,98,97,115,101,100,90,12,99,104,101,99,107,95,115,111, + 117,114,99,101,114,91,0,0,0,218,2,115,116,114,54,0, + 0,0,114,132,0,0,0,114,69,0,0,0,90,10,98,121, + 116,101,115,95,100,97,116,97,90,11,99,111,100,101,95,111, + 98,106,101,99,116,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,188,0,0,0,20,3,0,0,115,134,0, + 0,0,0,7,10,1,4,1,4,1,4,1,4,1,4,1, + 2,1,12,1,14,1,12,2,2,1,14,1,14,1,8,2, + 12,1,2,1,14,1,14,1,6,3,2,1,8,2,2,1, + 12,1,16,1,12,1,6,1,12,1,12,1,4,1,12,1, + 10,1,4,1,2,1,6,2,8,1,8,2,2,1,2,1, + 2,1,6,1,2,1,10,2,20,1,6,2,8,1,6,1, + 6,1,2,1,8,1,10,1,10,1,12,1,12,1,18,1, + 10,1,6,1,10,1,10,1,14,2,6,1,10,1,2,1, + 14,1,16,1,16,1,6,1,122,21,83,111,117,114,99,101, + 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,78, + 41,10,114,107,0,0,0,114,106,0,0,0,114,108,0,0, + 0,114,196,0,0,0,114,197,0,0,0,114,199,0,0,0, + 114,198,0,0,0,114,202,0,0,0,114,206,0,0,0,114, + 188,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,195,0,0,0,218,2,0, + 0,115,14,0,0,0,8,2,8,8,8,13,8,10,8,7, + 8,10,14,8,114,195,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,4,0,0,0,0,0,0,0,115,80, + 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, + 6,100,7,132,0,90,6,101,7,135,0,102,1,100,8,100, + 9,132,8,131,1,90,8,101,7,100,10,100,11,132,0,131, + 1,90,9,100,12,100,13,132,0,90,10,135,0,4,0,90, + 11,83,0,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, + 16,0,0,0,124,1,124,0,95,0,124,2,124,0,95,1, + 100,1,83,0,41,2,122,75,67,97,99,104,101,32,116,104, + 101,32,109,111,100,117,108,101,32,110,97,109,101,32,97,110, + 100,32,116,104,101,32,112,97,116,104,32,116,111,32,116,104, + 101,32,102,105,108,101,32,102,111,117,110,100,32,98,121,32, + 116,104,101,10,32,32,32,32,32,32,32,32,102,105,110,100, + 101,114,46,78,41,2,114,100,0,0,0,114,35,0,0,0, + 41,3,114,102,0,0,0,114,121,0,0,0,114,35,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,8,95,95,104,97,115,104,95,95,121,3,0,0,115,2, - 0,0,0,0,1,122,19,70,105,108,101,76,111,97,100,101, - 114,46,95,95,104,97,115,104,95,95,99,2,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115, - 16,0,0,0,116,0,116,1,124,0,131,2,160,2,124,1, - 161,1,83,0,41,1,122,100,76,111,97,100,32,97,32,109, - 111,100,117,108,101,32,102,114,111,109,32,97,32,102,105,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, - 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, - 100,46,10,10,32,32,32,32,32,32,32,32,41,3,218,5, - 115,117,112,101,114,114,212,0,0,0,114,194,0,0,0,41, - 2,114,102,0,0,0,114,121,0,0,0,41,1,114,213,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,194,0,0, - 0,124,3,0,0,115,2,0,0,0,0,10,122,22,70,105, - 108,101,76,111,97,100,101,114,46,108,111,97,100,95,109,111, - 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,1,0,0,0,67,0,0,0,115,6,0,0,0,124,0, - 106,0,83,0,41,1,122,58,82,101,116,117,114,110,32,116, - 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, - 111,117,114,99,101,32,102,105,108,101,32,97,115,32,102,111, - 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, - 114,46,41,1,114,35,0,0,0,41,2,114,102,0,0,0, - 114,121,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,159,0,0,0,136,3,0,0,115,2,0, - 0,0,0,3,122,23,70,105,108,101,76,111,97,100,101,114, - 46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0, - 0,0,0,0,0,0,3,0,0,0,9,0,0,0,67,0, - 0,0,115,32,0,0,0,116,0,160,1,124,1,100,1,161, - 2,143,10,125,2,124,2,160,2,161,0,83,0,81,0,82, - 0,88,0,100,2,83,0,41,3,122,39,82,101,116,117,114, - 110,32,116,104,101,32,100,97,116,97,32,102,114,111,109,32, - 112,97,116,104,32,97,115,32,114,97,119,32,98,121,116,101, - 115,46,218,1,114,78,41,3,114,50,0,0,0,114,51,0, - 0,0,90,4,114,101,97,100,41,3,114,102,0,0,0,114, - 35,0,0,0,114,55,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,200,0,0,0,141,3,0, - 0,115,4,0,0,0,0,2,14,1,122,19,70,105,108,101, - 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,41, - 12,114,107,0,0,0,114,106,0,0,0,114,108,0,0,0, - 114,109,0,0,0,114,186,0,0,0,114,215,0,0,0,114, - 217,0,0,0,114,118,0,0,0,114,194,0,0,0,114,159, - 0,0,0,114,200,0,0,0,90,13,95,95,99,108,97,115, - 115,99,101,108,108,95,95,114,2,0,0,0,114,2,0,0, - 0,41,1,114,213,0,0,0,114,4,0,0,0,114,212,0, - 0,0,106,3,0,0,115,12,0,0,0,12,5,8,6,8, - 4,8,3,16,12,12,5,114,212,0,0,0,99,0,0,0, - 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, - 0,115,46,0,0,0,101,0,90,1,100,0,90,2,100,1, - 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, - 90,5,100,6,100,7,156,1,100,8,100,9,132,2,90,6, - 100,10,83,0,41,11,218,16,83,111,117,114,99,101,70,105, - 108,101,76,111,97,100,101,114,122,62,67,111,110,99,114,101, - 116,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111, - 110,32,111,102,32,83,111,117,114,99,101,76,111,97,100,101, - 114,32,117,115,105,110,103,32,116,104,101,32,102,105,108,101, - 32,115,121,115,116,101,109,46,99,2,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,67,0,0,0,115,22,0, - 0,0,116,0,124,1,131,1,125,2,124,2,106,1,124,2, - 106,2,100,1,156,2,83,0,41,2,122,33,82,101,116,117, - 114,110,32,116,104,101,32,109,101,116,97,100,97,116,97,32, - 102,111,114,32,116,104,101,32,112,97,116,104,46,41,2,114, - 149,0,0,0,114,207,0,0,0,41,3,114,39,0,0,0, - 218,8,115,116,95,109,116,105,109,101,90,7,115,116,95,115, - 105,122,101,41,3,114,102,0,0,0,114,35,0,0,0,114, - 211,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,197,0,0,0,151,3,0,0,115,4,0,0, - 0,0,2,8,1,122,27,83,111,117,114,99,101,70,105,108, - 101,76,111,97,100,101,114,46,112,97,116,104,95,115,116,97, - 116,115,99,4,0,0,0,0,0,0,0,5,0,0,0,5, - 0,0,0,67,0,0,0,115,24,0,0,0,116,0,124,1, - 131,1,125,4,124,0,106,1,124,2,124,3,124,4,100,1, - 141,3,83,0,41,2,78,41,1,218,5,95,109,111,100,101, - 41,2,114,99,0,0,0,114,198,0,0,0,41,5,114,102, - 0,0,0,114,92,0,0,0,114,91,0,0,0,114,54,0, - 0,0,114,42,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,199,0,0,0,156,3,0,0,115, - 4,0,0,0,0,2,8,1,122,32,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,46,95,99,97,99,104, - 101,95,98,121,116,101,99,111,100,101,105,182,1,0,0,41, - 1,114,222,0,0,0,99,3,0,0,0,1,0,0,0,9, - 0,0,0,18,0,0,0,67,0,0,0,115,248,0,0,0, - 116,0,124,1,131,1,92,2,125,4,125,5,103,0,125,6, - 120,38,124,4,114,54,116,1,124,4,131,1,115,54,116,0, - 124,4,131,1,92,2,125,4,125,7,124,6,160,2,124,7, - 161,1,1,0,113,18,87,0,120,108,116,3,124,6,131,1, - 68,0,93,96,125,7,116,4,124,4,124,7,131,2,125,4, - 121,14,116,5,160,6,124,4,161,1,1,0,87,0,113,66, - 4,0,116,7,107,10,114,116,1,0,1,0,1,0,119,66, - 89,0,113,66,4,0,116,8,107,10,114,160,1,0,125,8, - 1,0,122,18,116,9,160,10,100,1,124,4,124,8,161,3, - 1,0,100,2,83,0,100,2,125,8,126,8,88,0,113,66, - 88,0,113,66,87,0,121,28,116,11,124,1,124,2,124,3, - 131,3,1,0,116,9,160,10,100,3,124,1,161,2,1,0, - 87,0,110,48,4,0,116,8,107,10,114,242,1,0,125,8, - 1,0,122,20,116,9,160,10,100,1,124,1,124,8,161,3, - 1,0,87,0,89,0,100,2,100,2,125,8,126,8,88,0, - 110,2,88,0,100,2,83,0,41,4,122,27,87,114,105,116, - 101,32,98,121,116,101,115,32,100,97,116,97,32,116,111,32, - 97,32,102,105,108,101,46,122,27,99,111,117,108,100,32,110, - 111,116,32,99,114,101,97,116,101,32,123,33,114,125,58,32, - 123,33,114,125,78,122,12,99,114,101,97,116,101,100,32,123, - 33,114,125,41,12,114,38,0,0,0,114,46,0,0,0,114, - 165,0,0,0,114,33,0,0,0,114,28,0,0,0,114,1, - 0,0,0,90,5,109,107,100,105,114,218,15,70,105,108,101, - 69,120,105,115,116,115,69,114,114,111,114,114,40,0,0,0, - 114,116,0,0,0,114,130,0,0,0,114,56,0,0,0,41, - 9,114,102,0,0,0,114,35,0,0,0,114,54,0,0,0, - 114,222,0,0,0,218,6,112,97,114,101,110,116,114,96,0, - 0,0,114,27,0,0,0,114,23,0,0,0,114,201,0,0, + 114,186,0,0,0,111,3,0,0,115,4,0,0,0,0,3, + 6,1,122,19,70,105,108,101,76,111,97,100,101,114,46,95, + 95,105,110,105,116,95,95,99,2,0,0,0,0,0,0,0, + 2,0,0,0,2,0,0,0,67,0,0,0,115,24,0,0, + 0,124,0,106,0,124,1,106,0,107,2,111,22,124,0,106, + 1,124,1,106,1,107,2,83,0,41,1,78,41,2,218,9, + 95,95,99,108,97,115,115,95,95,114,113,0,0,0,41,2, + 114,102,0,0,0,218,5,111,116,104,101,114,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,6,95,95,101, + 113,95,95,117,3,0,0,115,4,0,0,0,0,1,12,1, + 122,17,70,105,108,101,76,111,97,100,101,114,46,95,95,101, + 113,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,20,0,0,0,116,0,124, + 0,106,1,131,1,116,0,124,0,106,2,131,1,65,0,83, + 0,41,1,78,41,3,218,4,104,97,115,104,114,100,0,0, + 0,114,35,0,0,0,41,1,114,102,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,218,8,95,95, + 104,97,115,104,95,95,121,3,0,0,115,2,0,0,0,0, + 1,122,19,70,105,108,101,76,111,97,100,101,114,46,95,95, + 104,97,115,104,95,95,99,2,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,3,0,0,0,115,16,0,0,0, + 116,0,116,1,124,0,131,2,160,2,124,1,161,1,83,0, + 41,1,122,100,76,111,97,100,32,97,32,109,111,100,117,108, + 101,32,102,114,111,109,32,97,32,102,105,108,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, + 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,32,32,32,32,41,3,218,5,115,117,112,101, + 114,114,212,0,0,0,114,194,0,0,0,41,2,114,102,0, + 0,0,114,121,0,0,0,41,1,114,213,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,194,0,0,0,124,3,0, + 0,115,2,0,0,0,0,10,122,22,70,105,108,101,76,111, + 97,100,101,114,46,108,111,97,100,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,6,0,0,0,124,0,106,0,83,0, + 41,1,122,58,82,101,116,117,114,110,32,116,104,101,32,112, + 97,116,104,32,116,111,32,116,104,101,32,115,111,117,114,99, + 101,32,102,105,108,101,32,97,115,32,102,111,117,110,100,32, + 98,121,32,116,104,101,32,102,105,110,100,101,114,46,41,1, + 114,35,0,0,0,41,2,114,102,0,0,0,114,121,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,198,0,0,0,161,3,0,0,115,42,0,0,0,0,2, - 12,1,4,2,14,1,12,1,14,2,14,1,10,1,2,1, - 14,1,14,2,6,1,16,3,6,1,8,1,20,1,2,1, - 12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,46,115,101,116,95,100, - 97,116,97,78,41,7,114,107,0,0,0,114,106,0,0,0, - 114,108,0,0,0,114,109,0,0,0,114,197,0,0,0,114, - 199,0,0,0,114,198,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,114,220,0, - 0,0,147,3,0,0,115,6,0,0,0,12,4,8,5,8, - 5,114,220,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,64,0,0,0,115,32,0,0,0, - 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, - 132,0,90,4,100,4,100,5,132,0,90,5,100,6,83,0, - 41,7,218,20,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,122,45,76,111,97,100,101,114, - 32,119,104,105,99,104,32,104,97,110,100,108,101,115,32,115, - 111,117,114,99,101,108,101,115,115,32,102,105,108,101,32,105, - 109,112,111,114,116,115,46,99,2,0,0,0,0,0,0,0, - 5,0,0,0,5,0,0,0,67,0,0,0,115,68,0,0, - 0,124,0,160,0,124,1,161,1,125,2,124,0,160,1,124, - 2,161,1,125,3,124,1,124,2,100,1,156,2,125,4,116, - 2,124,3,124,1,124,4,131,3,1,0,116,3,116,4,124, - 3,131,1,100,2,100,0,133,2,25,0,124,1,124,2,100, - 3,141,3,83,0,41,4,78,41,2,114,100,0,0,0,114, - 35,0,0,0,114,126,0,0,0,41,2,114,100,0,0,0, - 114,91,0,0,0,41,5,114,159,0,0,0,114,200,0,0, - 0,114,133,0,0,0,114,145,0,0,0,114,208,0,0,0, - 41,5,114,102,0,0,0,114,121,0,0,0,114,35,0,0, - 0,114,54,0,0,0,114,132,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,188,0,0,0,196, - 3,0,0,115,18,0,0,0,0,1,10,1,10,4,2,1, - 8,2,12,1,2,1,14,1,2,1,122,29,83,111,117,114, - 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, - 46,103,101,116,95,99,111,100,101,99,2,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, - 0,0,0,100,1,83,0,41,2,122,39,82,101,116,117,114, - 110,32,78,111,110,101,32,97,115,32,116,104,101,114,101,32, - 105,115,32,110,111,32,115,111,117,114,99,101,32,99,111,100, - 101,46,78,114,2,0,0,0,41,2,114,102,0,0,0,114, - 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,202,0,0,0,212,3,0,0,115,2,0,0, - 0,0,2,122,31,83,111,117,114,99,101,108,101,115,115,70, - 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, - 117,114,99,101,78,41,6,114,107,0,0,0,114,106,0,0, - 0,114,108,0,0,0,114,109,0,0,0,114,188,0,0,0, - 114,202,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,225,0,0,0,192,3, - 0,0,115,4,0,0,0,12,4,8,16,114,225,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0, - 0,64,0,0,0,115,92,0,0,0,101,0,90,1,100,0, - 90,2,100,1,90,3,100,2,100,3,132,0,90,4,100,4, - 100,5,132,0,90,5,100,6,100,7,132,0,90,6,100,8, - 100,9,132,0,90,7,100,10,100,11,132,0,90,8,100,12, - 100,13,132,0,90,9,100,14,100,15,132,0,90,10,100,16, - 100,17,132,0,90,11,101,12,100,18,100,19,132,0,131,1, - 90,13,100,20,83,0,41,21,218,19,69,120,116,101,110,115, - 105,111,110,70,105,108,101,76,111,97,100,101,114,122,93,76, - 111,97,100,101,114,32,102,111,114,32,101,120,116,101,110,115, - 105,111,110,32,109,111,100,117,108,101,115,46,10,10,32,32, - 32,32,84,104,101,32,99,111,110,115,116,114,117,99,116,111, - 114,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111, - 32,119,111,114,107,32,119,105,116,104,32,70,105,108,101,70, - 105,110,100,101,114,46,10,10,32,32,32,32,99,3,0,0, - 0,0,0,0,0,3,0,0,0,2,0,0,0,67,0,0, - 0,115,16,0,0,0,124,1,124,0,95,0,124,2,124,0, - 95,1,100,0,83,0,41,1,78,41,2,114,100,0,0,0, - 114,35,0,0,0,41,3,114,102,0,0,0,114,100,0,0, - 0,114,35,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,186,0,0,0,229,3,0,0,115,4, - 0,0,0,0,1,6,1,122,28,69,120,116,101,110,115,105, - 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,105, - 110,105,116,95,95,99,2,0,0,0,0,0,0,0,2,0, - 0,0,2,0,0,0,67,0,0,0,115,24,0,0,0,124, - 0,106,0,124,1,106,0,107,2,111,22,124,0,106,1,124, - 1,106,1,107,2,83,0,41,1,78,41,2,114,213,0,0, - 0,114,113,0,0,0,41,2,114,102,0,0,0,114,214,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,215,0,0,0,233,3,0,0,115,4,0,0,0,0, - 1,12,1,122,26,69,120,116,101,110,115,105,111,110,70,105, - 108,101,76,111,97,100,101,114,46,95,95,101,113,95,95,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,20,0,0,0,116,0,124,0,106,1,131, - 1,116,0,124,0,106,2,131,1,65,0,83,0,41,1,78, - 41,3,114,216,0,0,0,114,100,0,0,0,114,35,0,0, - 0,41,1,114,102,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,217,0,0,0,237,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,5,0,0,0,67,0,0,0,115,36,0,0,0,116, - 0,160,1,116,2,106,3,124,1,161,2,125,2,116,0,160, - 4,100,1,124,1,106,5,124,0,106,6,161,3,1,0,124, - 2,83,0,41,2,122,38,67,114,101,97,116,101,32,97,110, - 32,117,110,105,116,105,97,108,105,122,101,100,32,101,120,116, - 101,110,115,105,111,110,32,109,111,100,117,108,101,122,38,101, - 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,32, - 123,33,114,125,32,108,111,97,100,101,100,32,102,114,111,109, - 32,123,33,114,125,41,7,114,116,0,0,0,114,189,0,0, - 0,114,143,0,0,0,90,14,99,114,101,97,116,101,95,100, - 121,110,97,109,105,99,114,130,0,0,0,114,100,0,0,0, - 114,35,0,0,0,41,3,114,102,0,0,0,114,166,0,0, - 0,114,191,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,187,0,0,0,240,3,0,0,115,10, - 0,0,0,0,2,4,1,10,1,6,1,12,1,122,33,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,46,99,114,101,97,116,101,95,109,111,100,117,108,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,5,0,0, - 0,67,0,0,0,115,36,0,0,0,116,0,160,1,116,2, - 106,3,124,1,161,2,1,0,116,0,160,4,100,1,124,0, - 106,5,124,0,106,6,161,3,1,0,100,2,83,0,41,3, - 122,30,73,110,105,116,105,97,108,105,122,101,32,97,110,32, - 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 122,40,101,120,116,101,110,115,105,111,110,32,109,111,100,117, - 108,101,32,123,33,114,125,32,101,120,101,99,117,116,101,100, - 32,102,114,111,109,32,123,33,114,125,78,41,7,114,116,0, - 0,0,114,189,0,0,0,114,143,0,0,0,90,12,101,120, - 101,99,95,100,121,110,97,109,105,99,114,130,0,0,0,114, - 100,0,0,0,114,35,0,0,0,41,2,114,102,0,0,0, - 114,191,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,192,0,0,0,248,3,0,0,115,6,0, - 0,0,0,2,14,1,6,1,122,31,69,120,116,101,110,115, - 105,111,110,70,105,108,101,76,111,97,100,101,114,46,101,120, - 101,99,95,109,111,100,117,108,101,99,2,0,0,0,0,0, - 0,0,2,0,0,0,4,0,0,0,3,0,0,0,115,36, - 0,0,0,116,0,124,0,106,1,131,1,100,1,25,0,137, - 0,116,2,135,0,102,1,100,2,100,3,132,8,116,3,68, - 0,131,1,131,1,83,0,41,4,122,49,82,101,116,117,114, - 110,32,84,114,117,101,32,105,102,32,116,104,101,32,101,120, - 116,101,110,115,105,111,110,32,109,111,100,117,108,101,32,105, - 115,32,97,32,112,97,99,107,97,103,101,46,114,29,0,0, - 0,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,51,0,0,0,115,26,0,0,0,124,0,93,18,125, - 1,136,0,100,0,124,1,23,0,107,2,86,0,1,0,113, - 2,100,1,83,0,41,2,114,186,0,0,0,78,114,2,0, - 0,0,41,2,114,22,0,0,0,218,6,115,117,102,102,105, - 120,41,1,218,9,102,105,108,101,95,110,97,109,101,114,2, - 0,0,0,114,4,0,0,0,250,9,60,103,101,110,101,120, - 112,114,62,1,4,0,0,115,2,0,0,0,4,1,122,49, - 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, - 100,101,114,46,105,115,95,112,97,99,107,97,103,101,46,60, - 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, - 62,41,4,114,38,0,0,0,114,35,0,0,0,218,3,97, - 110,121,218,18,69,88,84,69,78,83,73,79,78,95,83,85, - 70,70,73,88,69,83,41,2,114,102,0,0,0,114,121,0, - 0,0,114,2,0,0,0,41,1,114,228,0,0,0,114,4, - 0,0,0,114,161,0,0,0,254,3,0,0,115,6,0,0, - 0,0,2,14,1,12,1,122,30,69,120,116,101,110,115,105, - 111,110,70,105,108,101,76,111,97,100,101,114,46,105,115,95, - 112,97,99,107,97,103,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, - 0,100,1,83,0,41,2,122,63,82,101,116,117,114,110,32, - 78,111,110,101,32,97,115,32,97,110,32,101,120,116,101,110, - 115,105,111,110,32,109,111,100,117,108,101,32,99,97,110,110, - 111,116,32,99,114,101,97,116,101,32,97,32,99,111,100,101, - 32,111,98,106,101,99,116,46,78,114,2,0,0,0,41,2, - 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,188,0,0,0,4,4, - 0,0,115,2,0,0,0,0,2,122,28,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,103, - 101,116,95,99,111,100,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, - 0,100,1,83,0,41,2,122,53,82,101,116,117,114,110,32, - 78,111,110,101,32,97,115,32,101,120,116,101,110,115,105,111, - 110,32,109,111,100,117,108,101,115,32,104,97,118,101,32,110, + 114,159,0,0,0,136,3,0,0,115,2,0,0,0,0,3, + 122,23,70,105,108,101,76,111,97,100,101,114,46,103,101,116, + 95,102,105,108,101,110,97,109,101,99,2,0,0,0,0,0, + 0,0,3,0,0,0,9,0,0,0,67,0,0,0,115,32, + 0,0,0,116,0,160,1,124,1,100,1,161,2,143,10,125, + 2,124,2,160,2,161,0,83,0,81,0,82,0,88,0,100, + 2,83,0,41,3,122,39,82,101,116,117,114,110,32,116,104, + 101,32,100,97,116,97,32,102,114,111,109,32,112,97,116,104, + 32,97,115,32,114,97,119,32,98,121,116,101,115,46,218,1, + 114,78,41,3,114,50,0,0,0,114,51,0,0,0,90,4, + 114,101,97,100,41,3,114,102,0,0,0,114,35,0,0,0, + 114,55,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,200,0,0,0,141,3,0,0,115,4,0, + 0,0,0,2,14,1,122,19,70,105,108,101,76,111,97,100, + 101,114,46,103,101,116,95,100,97,116,97,41,12,114,107,0, + 0,0,114,106,0,0,0,114,108,0,0,0,114,109,0,0, + 0,114,186,0,0,0,114,215,0,0,0,114,217,0,0,0, + 114,118,0,0,0,114,194,0,0,0,114,159,0,0,0,114, + 200,0,0,0,90,13,95,95,99,108,97,115,115,99,101,108, + 108,95,95,114,2,0,0,0,114,2,0,0,0,41,1,114, + 213,0,0,0,114,4,0,0,0,114,212,0,0,0,106,3, + 0,0,115,12,0,0,0,12,5,8,6,8,4,8,3,16, + 12,12,5,114,212,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,3,0,0,0,64,0,0,0,115,46,0, + 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, + 100,3,132,0,90,4,100,4,100,5,132,0,90,5,100,6, + 100,7,156,1,100,8,100,9,132,2,90,6,100,10,83,0, + 41,11,218,16,83,111,117,114,99,101,70,105,108,101,76,111, + 97,100,101,114,122,62,67,111,110,99,114,101,116,101,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, + 32,83,111,117,114,99,101,76,111,97,100,101,114,32,117,115, + 105,110,103,32,116,104,101,32,102,105,108,101,32,115,121,115, + 116,101,109,46,99,2,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,22,0,0,0,116,0, + 124,1,131,1,125,2,124,2,106,1,124,2,106,2,100,1, + 156,2,83,0,41,2,122,33,82,101,116,117,114,110,32,116, + 104,101,32,109,101,116,97,100,97,116,97,32,102,111,114,32, + 116,104,101,32,112,97,116,104,46,41,2,114,149,0,0,0, + 114,207,0,0,0,41,3,114,39,0,0,0,218,8,115,116, + 95,109,116,105,109,101,90,7,115,116,95,115,105,122,101,41, + 3,114,102,0,0,0,114,35,0,0,0,114,211,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 197,0,0,0,151,3,0,0,115,4,0,0,0,0,2,8, + 1,122,27,83,111,117,114,99,101,70,105,108,101,76,111,97, + 100,101,114,46,112,97,116,104,95,115,116,97,116,115,99,4, + 0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,67, + 0,0,0,115,24,0,0,0,116,0,124,1,131,1,125,4, + 124,0,106,1,124,2,124,3,124,4,100,1,141,3,83,0, + 41,2,78,41,1,218,5,95,109,111,100,101,41,2,114,99, + 0,0,0,114,198,0,0,0,41,5,114,102,0,0,0,114, + 92,0,0,0,114,91,0,0,0,114,54,0,0,0,114,42, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,199,0,0,0,156,3,0,0,115,4,0,0,0, + 0,2,8,1,122,32,83,111,117,114,99,101,70,105,108,101, + 76,111,97,100,101,114,46,95,99,97,99,104,101,95,98,121, + 116,101,99,111,100,101,105,182,1,0,0,41,1,114,222,0, + 0,0,99,3,0,0,0,1,0,0,0,9,0,0,0,18, + 0,0,0,67,0,0,0,115,248,0,0,0,116,0,124,1, + 131,1,92,2,125,4,125,5,103,0,125,6,120,38,124,4, + 114,54,116,1,124,4,131,1,115,54,116,0,124,4,131,1, + 92,2,125,4,125,7,124,6,160,2,124,7,161,1,1,0, + 113,18,87,0,120,108,116,3,124,6,131,1,68,0,93,96, + 125,7,116,4,124,4,124,7,131,2,125,4,121,14,116,5, + 160,6,124,4,161,1,1,0,87,0,113,66,4,0,116,7, + 107,10,114,116,1,0,1,0,1,0,119,66,89,0,113,66, + 4,0,116,8,107,10,114,160,1,0,125,8,1,0,122,18, + 116,9,160,10,100,1,124,4,124,8,161,3,1,0,100,2, + 83,0,100,2,125,8,126,8,88,0,113,66,88,0,113,66, + 87,0,121,28,116,11,124,1,124,2,124,3,131,3,1,0, + 116,9,160,10,100,3,124,1,161,2,1,0,87,0,110,48, + 4,0,116,8,107,10,114,242,1,0,125,8,1,0,122,20, + 116,9,160,10,100,1,124,1,124,8,161,3,1,0,87,0, + 89,0,100,2,100,2,125,8,126,8,88,0,110,2,88,0, + 100,2,83,0,41,4,122,27,87,114,105,116,101,32,98,121, + 116,101,115,32,100,97,116,97,32,116,111,32,97,32,102,105, + 108,101,46,122,27,99,111,117,108,100,32,110,111,116,32,99, + 114,101,97,116,101,32,123,33,114,125,58,32,123,33,114,125, + 78,122,12,99,114,101,97,116,101,100,32,123,33,114,125,41, + 12,114,38,0,0,0,114,46,0,0,0,114,165,0,0,0, + 114,33,0,0,0,114,28,0,0,0,114,1,0,0,0,90, + 5,109,107,100,105,114,218,15,70,105,108,101,69,120,105,115, + 116,115,69,114,114,111,114,114,40,0,0,0,114,116,0,0, + 0,114,130,0,0,0,114,56,0,0,0,41,9,114,102,0, + 0,0,114,35,0,0,0,114,54,0,0,0,114,222,0,0, + 0,218,6,112,97,114,101,110,116,114,96,0,0,0,114,27, + 0,0,0,114,23,0,0,0,114,201,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,198,0,0, + 0,161,3,0,0,115,42,0,0,0,0,2,12,1,4,2, + 14,1,12,1,14,2,14,1,10,1,2,1,14,1,14,2, + 6,1,16,3,6,1,8,1,20,1,2,1,12,1,16,1, + 16,2,8,1,122,25,83,111,117,114,99,101,70,105,108,101, + 76,111,97,100,101,114,46,115,101,116,95,100,97,116,97,78, + 41,7,114,107,0,0,0,114,106,0,0,0,114,108,0,0, + 0,114,109,0,0,0,114,197,0,0,0,114,199,0,0,0, + 114,198,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,220,0,0,0,147,3, + 0,0,115,6,0,0,0,12,4,8,5,8,5,114,220,0, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,64,0,0,0,115,32,0,0,0,101,0,90,1, + 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, + 100,4,100,5,132,0,90,5,100,6,83,0,41,7,218,20, + 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, + 97,100,101,114,122,45,76,111,97,100,101,114,32,119,104,105, + 99,104,32,104,97,110,100,108,101,115,32,115,111,117,114,99, + 101,108,101,115,115,32,102,105,108,101,32,105,109,112,111,114, + 116,115,46,99,2,0,0,0,0,0,0,0,5,0,0,0, + 5,0,0,0,67,0,0,0,115,68,0,0,0,124,0,160, + 0,124,1,161,1,125,2,124,0,160,1,124,2,161,1,125, + 3,124,1,124,2,100,1,156,2,125,4,116,2,124,3,124, + 1,124,4,131,3,1,0,116,3,116,4,124,3,131,1,100, + 2,100,0,133,2,25,0,124,1,124,2,100,3,141,3,83, + 0,41,4,78,41,2,114,100,0,0,0,114,35,0,0,0, + 114,126,0,0,0,41,2,114,100,0,0,0,114,91,0,0, + 0,41,5,114,159,0,0,0,114,200,0,0,0,114,133,0, + 0,0,114,145,0,0,0,114,208,0,0,0,41,5,114,102, + 0,0,0,114,121,0,0,0,114,35,0,0,0,114,54,0, + 0,0,114,132,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,188,0,0,0,196,3,0,0,115, + 18,0,0,0,0,1,10,1,10,4,2,1,8,2,12,1, + 2,1,14,1,2,1,122,29,83,111,117,114,99,101,108,101, + 115,115,70,105,108,101,76,111,97,100,101,114,46,103,101,116, + 95,99,111,100,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, + 1,83,0,41,2,122,39,82,101,116,117,114,110,32,78,111, + 110,101,32,97,115,32,116,104,101,114,101,32,105,115,32,110, 111,32,115,111,117,114,99,101,32,99,111,100,101,46,78,114, 2,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 202,0,0,0,8,4,0,0,115,2,0,0,0,0,2,122, - 30,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,6,0,0,0,124,0,106,0,83,0,41, - 1,122,58,82,101,116,117,114,110,32,116,104,101,32,112,97, - 116,104,32,116,111,32,116,104,101,32,115,111,117,114,99,101, - 32,102,105,108,101,32,97,115,32,102,111,117,110,100,32,98, - 121,32,116,104,101,32,102,105,110,100,101,114,46,41,1,114, - 35,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 159,0,0,0,12,4,0,0,115,2,0,0,0,0,3,122, - 32,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,102,105,108,101,110,97,109, - 101,78,41,14,114,107,0,0,0,114,106,0,0,0,114,108, - 0,0,0,114,109,0,0,0,114,186,0,0,0,114,215,0, - 0,0,114,217,0,0,0,114,187,0,0,0,114,192,0,0, - 0,114,161,0,0,0,114,188,0,0,0,114,202,0,0,0, - 114,118,0,0,0,114,159,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,226, - 0,0,0,221,3,0,0,115,18,0,0,0,12,8,8,4, - 8,4,8,3,8,8,8,6,8,6,8,4,8,4,114,226, - 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,64,0,0,0,115,96,0,0,0,101,0,90, - 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, - 4,100,4,100,5,132,0,90,5,100,6,100,7,132,0,90, - 6,100,8,100,9,132,0,90,7,100,10,100,11,132,0,90, - 8,100,12,100,13,132,0,90,9,100,14,100,15,132,0,90, - 10,100,16,100,17,132,0,90,11,100,18,100,19,132,0,90, - 12,100,20,100,21,132,0,90,13,100,22,83,0,41,23,218, - 14,95,78,97,109,101,115,112,97,99,101,80,97,116,104,97, - 38,1,0,0,82,101,112,114,101,115,101,110,116,115,32,97, - 32,110,97,109,101,115,112,97,99,101,32,112,97,99,107,97, - 103,101,39,115,32,112,97,116,104,46,32,32,73,116,32,117, - 115,101,115,32,116,104,101,32,109,111,100,117,108,101,32,110, - 97,109,101,10,32,32,32,32,116,111,32,102,105,110,100,32, - 105,116,115,32,112,97,114,101,110,116,32,109,111,100,117,108, - 101,44,32,97,110,100,32,102,114,111,109,32,116,104,101,114, - 101,32,105,116,32,108,111,111,107,115,32,117,112,32,116,104, - 101,32,112,97,114,101,110,116,39,115,10,32,32,32,32,95, - 95,112,97,116,104,95,95,46,32,32,87,104,101,110,32,116, - 104,105,115,32,99,104,97,110,103,101,115,44,32,116,104,101, - 32,109,111,100,117,108,101,39,115,32,111,119,110,32,112,97, - 116,104,32,105,115,32,114,101,99,111,109,112,117,116,101,100, - 44,10,32,32,32,32,117,115,105,110,103,32,112,97,116,104, - 95,102,105,110,100,101,114,46,32,32,70,111,114,32,116,111, - 112,45,108,101,118,101,108,32,109,111,100,117,108,101,115,44, - 32,116,104,101,32,112,97,114,101,110,116,32,109,111,100,117, - 108,101,39,115,32,112,97,116,104,10,32,32,32,32,105,115, - 32,115,121,115,46,112,97,116,104,46,99,4,0,0,0,0, - 0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115, - 36,0,0,0,124,1,124,0,95,0,124,2,124,0,95,1, - 116,2,124,0,160,3,161,0,131,1,124,0,95,4,124,3, - 124,0,95,5,100,0,83,0,41,1,78,41,6,218,5,95, - 110,97,109,101,218,5,95,112,97,116,104,114,95,0,0,0, - 218,16,95,103,101,116,95,112,97,114,101,110,116,95,112,97, - 116,104,218,17,95,108,97,115,116,95,112,97,114,101,110,116, - 95,112,97,116,104,218,12,95,112,97,116,104,95,102,105,110, - 100,101,114,41,4,114,102,0,0,0,114,100,0,0,0,114, - 35,0,0,0,218,11,112,97,116,104,95,102,105,110,100,101, - 114,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,186,0,0,0,25,4,0,0,115,8,0,0,0,0,1, - 6,1,6,1,14,1,122,23,95,78,97,109,101,115,112,97, - 99,101,80,97,116,104,46,95,95,105,110,105,116,95,95,99, - 1,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, - 67,0,0,0,115,38,0,0,0,124,0,106,0,160,1,100, - 1,161,1,92,3,125,1,125,2,125,3,124,2,100,2,107, - 2,114,30,100,3,83,0,124,1,100,4,102,2,83,0,41, - 5,122,62,82,101,116,117,114,110,115,32,97,32,116,117,112, - 108,101,32,111,102,32,40,112,97,114,101,110,116,45,109,111, - 100,117,108,101,45,110,97,109,101,44,32,112,97,114,101,110, - 116,45,112,97,116,104,45,97,116,116,114,45,110,97,109,101, - 41,114,59,0,0,0,114,30,0,0,0,41,2,114,6,0, - 0,0,114,35,0,0,0,90,8,95,95,112,97,116,104,95, - 95,41,2,114,233,0,0,0,114,32,0,0,0,41,4,114, - 102,0,0,0,114,224,0,0,0,218,3,100,111,116,90,2, - 109,101,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,23,95,102,105,110,100,95,112,97,114,101,110,116,95, - 112,97,116,104,95,110,97,109,101,115,31,4,0,0,115,8, - 0,0,0,0,2,18,1,8,2,4,3,122,38,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,95,102,105,110, - 100,95,112,97,114,101,110,116,95,112,97,116,104,95,110,97, - 109,101,115,99,1,0,0,0,0,0,0,0,3,0,0,0, - 3,0,0,0,67,0,0,0,115,28,0,0,0,124,0,160, - 0,161,0,92,2,125,1,125,2,116,1,116,2,106,3,124, - 1,25,0,124,2,131,2,83,0,41,1,78,41,4,114,240, - 0,0,0,114,112,0,0,0,114,6,0,0,0,218,7,109, - 111,100,117,108,101,115,41,3,114,102,0,0,0,90,18,112, - 97,114,101,110,116,95,109,111,100,117,108,101,95,110,97,109, - 101,90,14,112,97,116,104,95,97,116,116,114,95,110,97,109, - 101,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,235,0,0,0,41,4,0,0,115,4,0,0,0,0,1, - 12,1,122,31,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,46,95,103,101,116,95,112,97,114,101,110,116,95,112, - 97,116,104,99,1,0,0,0,0,0,0,0,3,0,0,0, - 4,0,0,0,67,0,0,0,115,80,0,0,0,116,0,124, - 0,160,1,161,0,131,1,125,1,124,1,124,0,106,2,107, - 3,114,74,124,0,160,3,124,0,106,4,124,1,161,2,125, - 2,124,2,100,0,107,9,114,68,124,2,106,5,100,0,107, - 8,114,68,124,2,106,6,114,68,124,2,106,6,124,0,95, - 7,124,1,124,0,95,2,124,0,106,7,83,0,41,1,78, - 41,8,114,95,0,0,0,114,235,0,0,0,114,236,0,0, - 0,114,237,0,0,0,114,233,0,0,0,114,122,0,0,0, - 114,158,0,0,0,114,234,0,0,0,41,3,114,102,0,0, - 0,90,11,112,97,114,101,110,116,95,112,97,116,104,114,166, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,12,95,114,101,99,97,108,99,117,108,97,116,101, - 45,4,0,0,115,16,0,0,0,0,2,12,1,10,1,14, - 3,18,1,6,1,8,1,6,1,122,27,95,78,97,109,101, - 115,112,97,99,101,80,97,116,104,46,95,114,101,99,97,108, - 99,117,108,97,116,101,99,1,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,67,0,0,0,115,12,0,0,0, - 116,0,124,0,160,1,161,0,131,1,83,0,41,1,78,41, - 2,218,4,105,116,101,114,114,242,0,0,0,41,1,114,102, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,8,95,95,105,116,101,114,95,95,58,4,0,0, - 115,2,0,0,0,0,1,122,23,95,78,97,109,101,115,112, - 97,99,101,80,97,116,104,46,95,95,105,116,101,114,95,95, - 99,3,0,0,0,0,0,0,0,3,0,0,0,3,0,0, - 0,67,0,0,0,115,14,0,0,0,124,2,124,0,106,0, - 124,1,60,0,100,0,83,0,41,1,78,41,1,114,234,0, - 0,0,41,3,114,102,0,0,0,218,5,105,110,100,101,120, - 114,35,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,218,11,95,95,115,101,116,105,116,101,109,95, - 95,61,4,0,0,115,2,0,0,0,0,1,122,26,95,78, - 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,115, - 101,116,105,116,101,109,95,95,99,1,0,0,0,0,0,0, - 0,1,0,0,0,3,0,0,0,67,0,0,0,115,12,0, - 0,0,116,0,124,0,160,1,161,0,131,1,83,0,41,1, - 78,41,2,114,31,0,0,0,114,242,0,0,0,41,1,114, + 202,0,0,0,212,3,0,0,115,2,0,0,0,0,2,122, + 31,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, + 111,97,100,101,114,46,103,101,116,95,115,111,117,114,99,101, + 78,41,6,114,107,0,0,0,114,106,0,0,0,114,108,0, + 0,0,114,109,0,0,0,114,188,0,0,0,114,202,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,225,0,0,0,192,3,0,0,115,4, + 0,0,0,12,4,8,16,114,225,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, + 0,115,92,0,0,0,101,0,90,1,100,0,90,2,100,1, + 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, + 90,5,100,6,100,7,132,0,90,6,100,8,100,9,132,0, + 90,7,100,10,100,11,132,0,90,8,100,12,100,13,132,0, + 90,9,100,14,100,15,132,0,90,10,100,16,100,17,132,0, + 90,11,101,12,100,18,100,19,132,0,131,1,90,13,100,20, + 83,0,41,21,218,19,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,122,93,76,111,97,100,101, + 114,32,102,111,114,32,101,120,116,101,110,115,105,111,110,32, + 109,111,100,117,108,101,115,46,10,10,32,32,32,32,84,104, + 101,32,99,111,110,115,116,114,117,99,116,111,114,32,105,115, + 32,100,101,115,105,103,110,101,100,32,116,111,32,119,111,114, + 107,32,119,105,116,104,32,70,105,108,101,70,105,110,100,101, + 114,46,10,10,32,32,32,32,99,3,0,0,0,0,0,0, + 0,3,0,0,0,2,0,0,0,67,0,0,0,115,16,0, + 0,0,124,1,124,0,95,0,124,2,124,0,95,1,100,0, + 83,0,41,1,78,41,2,114,100,0,0,0,114,35,0,0, + 0,41,3,114,102,0,0,0,114,100,0,0,0,114,35,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,186,0,0,0,229,3,0,0,115,4,0,0,0,0, + 1,6,1,122,28,69,120,116,101,110,115,105,111,110,70,105, + 108,101,76,111,97,100,101,114,46,95,95,105,110,105,116,95, + 95,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0, + 0,0,67,0,0,0,115,24,0,0,0,124,0,106,0,124, + 1,106,0,107,2,111,22,124,0,106,1,124,1,106,1,107, + 2,83,0,41,1,78,41,2,114,213,0,0,0,114,113,0, + 0,0,41,2,114,102,0,0,0,114,214,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,215,0, + 0,0,233,3,0,0,115,4,0,0,0,0,1,12,1,122, + 26,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, + 97,100,101,114,46,95,95,101,113,95,95,99,1,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 115,20,0,0,0,116,0,124,0,106,1,131,1,116,0,124, + 0,106,2,131,1,65,0,83,0,41,1,78,41,3,114,216, + 0,0,0,114,100,0,0,0,114,35,0,0,0,41,1,114, 102,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,7,95,95,108,101,110,95,95,64,4,0,0, - 115,2,0,0,0,0,1,122,22,95,78,97,109,101,115,112, - 97,99,101,80,97,116,104,46,95,95,108,101,110,95,95,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,12,0,0,0,100,1,160,0,124,0,106, - 1,161,1,83,0,41,2,78,122,20,95,78,97,109,101,115, - 112,97,99,101,80,97,116,104,40,123,33,114,125,41,41,2, - 114,48,0,0,0,114,234,0,0,0,41,1,114,102,0,0, + 0,0,0,114,217,0,0,0,237,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,5,0, + 0,0,67,0,0,0,115,36,0,0,0,116,0,160,1,116, + 2,106,3,124,1,161,2,125,2,116,0,160,4,100,1,124, + 1,106,5,124,0,106,6,161,3,1,0,124,2,83,0,41, + 2,122,38,67,114,101,97,116,101,32,97,110,32,117,110,105, + 116,105,97,108,105,122,101,100,32,101,120,116,101,110,115,105, + 111,110,32,109,111,100,117,108,101,122,38,101,120,116,101,110, + 115,105,111,110,32,109,111,100,117,108,101,32,123,33,114,125, + 32,108,111,97,100,101,100,32,102,114,111,109,32,123,33,114, + 125,41,7,114,116,0,0,0,114,189,0,0,0,114,143,0, + 0,0,90,14,99,114,101,97,116,101,95,100,121,110,97,109, + 105,99,114,130,0,0,0,114,100,0,0,0,114,35,0,0, + 0,41,3,114,102,0,0,0,114,166,0,0,0,114,191,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,187,0,0,0,240,3,0,0,115,10,0,0,0,0, + 2,4,1,10,1,6,1,12,1,122,33,69,120,116,101,110, + 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,99, + 114,101,97,116,101,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,5,0,0,0,67,0,0, + 0,115,36,0,0,0,116,0,160,1,116,2,106,3,124,1, + 161,2,1,0,116,0,160,4,100,1,124,0,106,5,124,0, + 106,6,161,3,1,0,100,2,83,0,41,3,122,30,73,110, + 105,116,105,97,108,105,122,101,32,97,110,32,101,120,116,101, + 110,115,105,111,110,32,109,111,100,117,108,101,122,40,101,120, + 116,101,110,115,105,111,110,32,109,111,100,117,108,101,32,123, + 33,114,125,32,101,120,101,99,117,116,101,100,32,102,114,111, + 109,32,123,33,114,125,78,41,7,114,116,0,0,0,114,189, + 0,0,0,114,143,0,0,0,90,12,101,120,101,99,95,100, + 121,110,97,109,105,99,114,130,0,0,0,114,100,0,0,0, + 114,35,0,0,0,41,2,114,102,0,0,0,114,191,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,8,95,95,114,101,112,114,95,95,67,4,0,0,115,2, - 0,0,0,0,1,122,23,95,78,97,109,101,115,112,97,99, - 101,80,97,116,104,46,95,95,114,101,112,114,95,95,99,2, - 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, - 0,0,0,115,12,0,0,0,124,1,124,0,160,0,161,0, - 107,6,83,0,41,1,78,41,1,114,242,0,0,0,41,2, - 114,102,0,0,0,218,4,105,116,101,109,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,218,12,95,95,99,111, - 110,116,97,105,110,115,95,95,70,4,0,0,115,2,0,0, - 0,0,1,122,27,95,78,97,109,101,115,112,97,99,101,80, - 97,116,104,46,95,95,99,111,110,116,97,105,110,115,95,95, - 99,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0, - 0,67,0,0,0,115,16,0,0,0,124,0,106,0,160,1, - 124,1,161,1,1,0,100,0,83,0,41,1,78,41,2,114, - 234,0,0,0,114,165,0,0,0,41,2,114,102,0,0,0, - 114,249,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,165,0,0,0,73,4,0,0,115,2,0, - 0,0,0,1,122,21,95,78,97,109,101,115,112,97,99,101, - 80,97,116,104,46,97,112,112,101,110,100,78,41,14,114,107, - 0,0,0,114,106,0,0,0,114,108,0,0,0,114,109,0, - 0,0,114,186,0,0,0,114,240,0,0,0,114,235,0,0, - 0,114,242,0,0,0,114,244,0,0,0,114,246,0,0,0, - 114,247,0,0,0,114,248,0,0,0,114,250,0,0,0,114, - 165,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,232,0,0,0,18,4,0, - 0,115,20,0,0,0,12,7,8,6,8,10,8,4,8,13, - 8,3,8,3,8,3,8,3,8,3,114,232,0,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 64,0,0,0,115,80,0,0,0,101,0,90,1,100,0,90, - 2,100,1,100,2,132,0,90,3,101,4,100,3,100,4,132, - 0,131,1,90,5,100,5,100,6,132,0,90,6,100,7,100, - 8,132,0,90,7,100,9,100,10,132,0,90,8,100,11,100, - 12,132,0,90,9,100,13,100,14,132,0,90,10,100,15,100, - 16,132,0,90,11,100,17,83,0,41,18,218,16,95,78,97, - 109,101,115,112,97,99,101,76,111,97,100,101,114,99,4,0, - 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, - 0,0,115,18,0,0,0,116,0,124,1,124,2,124,3,131, - 3,124,0,95,1,100,0,83,0,41,1,78,41,2,114,232, - 0,0,0,114,234,0,0,0,41,4,114,102,0,0,0,114, - 100,0,0,0,114,35,0,0,0,114,238,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,114,186,0, - 0,0,79,4,0,0,115,2,0,0,0,0,1,122,25,95, - 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, - 95,95,105,110,105,116,95,95,99,2,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,67,0,0,0,115,12,0, - 0,0,100,1,160,0,124,1,106,1,161,1,83,0,41,2, - 122,115,82,101,116,117,114,110,32,114,101,112,114,32,102,111, - 114,32,116,104,101,32,109,111,100,117,108,101,46,10,10,32, - 32,32,32,32,32,32,32,84,104,101,32,109,101,116,104,111, - 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 32,32,84,104,101,32,105,109,112,111,114,116,32,109,97,99, - 104,105,110,101,114,121,32,100,111,101,115,32,116,104,101,32, - 106,111,98,32,105,116,115,101,108,102,46,10,10,32,32,32, - 32,32,32,32,32,122,25,60,109,111,100,117,108,101,32,123, - 33,114,125,32,40,110,97,109,101,115,112,97,99,101,41,62, - 41,2,114,48,0,0,0,114,107,0,0,0,41,2,114,172, - 0,0,0,114,191,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,11,109,111,100,117,108,101,95, - 114,101,112,114,82,4,0,0,115,2,0,0,0,0,7,122, - 28,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, - 114,46,109,111,100,117,108,101,95,114,101,112,114,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,83,0,41,2,78,84,114, - 2,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 161,0,0,0,91,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, + 114,192,0,0,0,248,3,0,0,115,6,0,0,0,0,2, + 14,1,6,1,122,31,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,101,120,101,99,95,109, + 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,4,0,0,0,3,0,0,0,115,36,0,0,0,116, + 0,124,0,106,1,131,1,100,1,25,0,137,0,116,2,135, + 0,102,1,100,2,100,3,132,8,116,3,68,0,131,1,131, + 1,83,0,41,4,122,49,82,101,116,117,114,110,32,84,114, + 117,101,32,105,102,32,116,104,101,32,101,120,116,101,110,115, + 105,111,110,32,109,111,100,117,108,101,32,105,115,32,97,32, + 112,97,99,107,97,103,101,46,114,29,0,0,0,99,1,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,51,0, + 0,0,115,26,0,0,0,124,0,93,18,125,1,136,0,100, + 0,124,1,23,0,107,2,86,0,1,0,113,2,100,1,83, + 0,41,2,114,186,0,0,0,78,114,2,0,0,0,41,2, + 114,22,0,0,0,218,6,115,117,102,102,105,120,41,1,218, + 9,102,105,108,101,95,110,97,109,101,114,2,0,0,0,114, + 4,0,0,0,250,9,60,103,101,110,101,120,112,114,62,1, + 4,0,0,115,2,0,0,0,4,1,122,49,69,120,116,101, + 110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,46, + 105,115,95,112,97,99,107,97,103,101,46,60,108,111,99,97, + 108,115,62,46,60,103,101,110,101,120,112,114,62,41,4,114, + 38,0,0,0,114,35,0,0,0,218,3,97,110,121,218,18, + 69,88,84,69,78,83,73,79,78,95,83,85,70,70,73,88, + 69,83,41,2,114,102,0,0,0,114,121,0,0,0,114,2, + 0,0,0,41,1,114,228,0,0,0,114,4,0,0,0,114, + 161,0,0,0,254,3,0,0,115,6,0,0,0,0,2,14, + 1,12,1,122,30,69,120,116,101,110,115,105,111,110,70,105, + 108,101,76,111,97,100,101,114,46,105,115,95,112,97,99,107, + 97,103,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, + 0,41,2,122,63,82,101,116,117,114,110,32,78,111,110,101, + 32,97,115,32,97,110,32,101,120,116,101,110,115,105,111,110, + 32,109,111,100,117,108,101,32,99,97,110,110,111,116,32,99, + 114,101,97,116,101,32,97,32,99,111,100,101,32,111,98,106, + 101,99,116,46,78,114,2,0,0,0,41,2,114,102,0,0, + 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,188,0,0,0,4,4,0,0,115,2, + 0,0,0,0,2,122,28,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,99, + 111,100,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, + 0,41,2,122,53,82,101,116,117,114,110,32,78,111,110,101, + 32,97,115,32,101,120,116,101,110,115,105,111,110,32,109,111, + 100,117,108,101,115,32,104,97,118,101,32,110,111,32,115,111, + 117,114,99,101,32,99,111,100,101,46,78,114,2,0,0,0, + 41,2,114,102,0,0,0,114,121,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,202,0,0,0, + 8,4,0,0,115,2,0,0,0,0,2,122,30,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,6,0,0,0,124,0,106,0,83,0,41,1,122,58,82, + 101,116,117,114,110,32,116,104,101,32,112,97,116,104,32,116, + 111,32,116,104,101,32,115,111,117,114,99,101,32,102,105,108, + 101,32,97,115,32,102,111,117,110,100,32,98,121,32,116,104, + 101,32,102,105,110,100,101,114,46,41,1,114,35,0,0,0, + 41,2,114,102,0,0,0,114,121,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,159,0,0,0, + 12,4,0,0,115,2,0,0,0,0,3,122,32,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,102,105,108,101,110,97,109,101,78,41,14, + 114,107,0,0,0,114,106,0,0,0,114,108,0,0,0,114, + 109,0,0,0,114,186,0,0,0,114,215,0,0,0,114,217, + 0,0,0,114,187,0,0,0,114,192,0,0,0,114,161,0, + 0,0,114,188,0,0,0,114,202,0,0,0,114,118,0,0, + 0,114,159,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,226,0,0,0,221, + 3,0,0,115,18,0,0,0,12,8,8,4,8,4,8,3, + 8,8,8,6,8,6,8,4,8,4,114,226,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 64,0,0,0,115,96,0,0,0,101,0,90,1,100,0,90, + 2,100,1,90,3,100,2,100,3,132,0,90,4,100,4,100, + 5,132,0,90,5,100,6,100,7,132,0,90,6,100,8,100, + 9,132,0,90,7,100,10,100,11,132,0,90,8,100,12,100, + 13,132,0,90,9,100,14,100,15,132,0,90,10,100,16,100, + 17,132,0,90,11,100,18,100,19,132,0,90,12,100,20,100, + 21,132,0,90,13,100,22,83,0,41,23,218,14,95,78,97, + 109,101,115,112,97,99,101,80,97,116,104,97,38,1,0,0, + 82,101,112,114,101,115,101,110,116,115,32,97,32,110,97,109, + 101,115,112,97,99,101,32,112,97,99,107,97,103,101,39,115, + 32,112,97,116,104,46,32,32,73,116,32,117,115,101,115,32, + 116,104,101,32,109,111,100,117,108,101,32,110,97,109,101,10, + 32,32,32,32,116,111,32,102,105,110,100,32,105,116,115,32, + 112,97,114,101,110,116,32,109,111,100,117,108,101,44,32,97, + 110,100,32,102,114,111,109,32,116,104,101,114,101,32,105,116, + 32,108,111,111,107,115,32,117,112,32,116,104,101,32,112,97, + 114,101,110,116,39,115,10,32,32,32,32,95,95,112,97,116, + 104,95,95,46,32,32,87,104,101,110,32,116,104,105,115,32, + 99,104,97,110,103,101,115,44,32,116,104,101,32,109,111,100, + 117,108,101,39,115,32,111,119,110,32,112,97,116,104,32,105, + 115,32,114,101,99,111,109,112,117,116,101,100,44,10,32,32, + 32,32,117,115,105,110,103,32,112,97,116,104,95,102,105,110, + 100,101,114,46,32,32,70,111,114,32,116,111,112,45,108,101, + 118,101,108,32,109,111,100,117,108,101,115,44,32,116,104,101, + 32,112,97,114,101,110,116,32,109,111,100,117,108,101,39,115, + 32,112,97,116,104,10,32,32,32,32,105,115,32,115,121,115, + 46,112,97,116,104,46,99,4,0,0,0,0,0,0,0,4, + 0,0,0,3,0,0,0,67,0,0,0,115,36,0,0,0, + 124,1,124,0,95,0,124,2,124,0,95,1,116,2,124,0, + 160,3,161,0,131,1,124,0,95,4,124,3,124,0,95,5, + 100,0,83,0,41,1,78,41,6,218,5,95,110,97,109,101, + 218,5,95,112,97,116,104,114,95,0,0,0,218,16,95,103, + 101,116,95,112,97,114,101,110,116,95,112,97,116,104,218,17, + 95,108,97,115,116,95,112,97,114,101,110,116,95,112,97,116, + 104,218,12,95,112,97,116,104,95,102,105,110,100,101,114,41, + 4,114,102,0,0,0,114,100,0,0,0,114,35,0,0,0, + 218,11,112,97,116,104,95,102,105,110,100,101,114,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,186,0,0, + 0,25,4,0,0,115,8,0,0,0,0,1,6,1,6,1, + 14,1,122,23,95,78,97,109,101,115,112,97,99,101,80,97, + 116,104,46,95,95,105,110,105,116,95,95,99,1,0,0,0, + 0,0,0,0,4,0,0,0,3,0,0,0,67,0,0,0, + 115,38,0,0,0,124,0,106,0,160,1,100,1,161,1,92, + 3,125,1,125,2,125,3,124,2,100,2,107,2,114,30,100, + 3,83,0,124,1,100,4,102,2,83,0,41,5,122,62,82, + 101,116,117,114,110,115,32,97,32,116,117,112,108,101,32,111, + 102,32,40,112,97,114,101,110,116,45,109,111,100,117,108,101, + 45,110,97,109,101,44,32,112,97,114,101,110,116,45,112,97, + 116,104,45,97,116,116,114,45,110,97,109,101,41,114,59,0, + 0,0,114,30,0,0,0,41,2,114,6,0,0,0,114,35, + 0,0,0,90,8,95,95,112,97,116,104,95,95,41,2,114, + 233,0,0,0,114,32,0,0,0,41,4,114,102,0,0,0, + 114,224,0,0,0,218,3,100,111,116,90,2,109,101,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,218,23,95, + 102,105,110,100,95,112,97,114,101,110,116,95,112,97,116,104, + 95,110,97,109,101,115,31,4,0,0,115,8,0,0,0,0, + 2,18,1,8,2,4,3,122,38,95,78,97,109,101,115,112, + 97,99,101,80,97,116,104,46,95,102,105,110,100,95,112,97, + 114,101,110,116,95,112,97,116,104,95,110,97,109,101,115,99, + 1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, + 67,0,0,0,115,28,0,0,0,124,0,160,0,161,0,92, + 2,125,1,125,2,116,1,116,2,106,3,124,1,25,0,124, + 2,131,2,83,0,41,1,78,41,4,114,240,0,0,0,114, + 112,0,0,0,114,6,0,0,0,218,7,109,111,100,117,108, + 101,115,41,3,114,102,0,0,0,90,18,112,97,114,101,110, + 116,95,109,111,100,117,108,101,95,110,97,109,101,90,14,112, + 97,116,104,95,97,116,116,114,95,110,97,109,101,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,235,0,0, + 0,41,4,0,0,115,4,0,0,0,0,1,12,1,122,31, + 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, + 103,101,116,95,112,97,114,101,110,116,95,112,97,116,104,99, + 1,0,0,0,0,0,0,0,3,0,0,0,4,0,0,0, + 67,0,0,0,115,80,0,0,0,116,0,124,0,160,1,161, + 0,131,1,125,1,124,1,124,0,106,2,107,3,114,74,124, + 0,160,3,124,0,106,4,124,1,161,2,125,2,124,2,100, + 0,107,9,114,68,124,2,106,5,100,0,107,8,114,68,124, + 2,106,6,114,68,124,2,106,6,124,0,95,7,124,1,124, + 0,95,2,124,0,106,7,83,0,41,1,78,41,8,114,95, + 0,0,0,114,235,0,0,0,114,236,0,0,0,114,237,0, + 0,0,114,233,0,0,0,114,122,0,0,0,114,158,0,0, + 0,114,234,0,0,0,41,3,114,102,0,0,0,90,11,112, + 97,114,101,110,116,95,112,97,116,104,114,166,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,12, + 95,114,101,99,97,108,99,117,108,97,116,101,45,4,0,0, + 115,16,0,0,0,0,2,12,1,10,1,14,3,18,1,6, + 1,8,1,6,1,122,27,95,78,97,109,101,115,112,97,99, + 101,80,97,116,104,46,95,114,101,99,97,108,99,117,108,97, + 116,101,99,1,0,0,0,0,0,0,0,1,0,0,0,3, + 0,0,0,67,0,0,0,115,12,0,0,0,116,0,124,0, + 160,1,161,0,131,1,83,0,41,1,78,41,2,218,4,105, + 116,101,114,114,242,0,0,0,41,1,114,102,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,8, + 95,95,105,116,101,114,95,95,58,4,0,0,115,2,0,0, + 0,0,1,122,23,95,78,97,109,101,115,112,97,99,101,80, + 97,116,104,46,95,95,105,116,101,114,95,95,99,3,0,0, + 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0, + 0,115,14,0,0,0,124,2,124,0,106,0,124,1,60,0, + 100,0,83,0,41,1,78,41,1,114,234,0,0,0,41,3, + 114,102,0,0,0,218,5,105,110,100,101,120,114,35,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,11,95,95,115,101,116,105,116,101,109,95,95,61,4,0, + 0,115,2,0,0,0,0,1,122,26,95,78,97,109,101,115, + 112,97,99,101,80,97,116,104,46,95,95,115,101,116,105,116, + 101,109,95,95,99,1,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,115,12,0,0,0,116,0, + 124,0,160,1,161,0,131,1,83,0,41,1,78,41,2,114, + 31,0,0,0,114,242,0,0,0,41,1,114,102,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 7,95,95,108,101,110,95,95,64,4,0,0,115,2,0,0, + 0,0,1,122,22,95,78,97,109,101,115,112,97,99,101,80, + 97,116,104,46,95,95,108,101,110,95,95,99,1,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 115,12,0,0,0,100,1,160,0,124,0,106,1,161,1,83, + 0,41,2,78,122,20,95,78,97,109,101,115,112,97,99,101, + 80,97,116,104,40,123,33,114,125,41,41,2,114,48,0,0, + 0,114,234,0,0,0,41,1,114,102,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,218,8,95,95, + 114,101,112,114,95,95,67,4,0,0,115,2,0,0,0,0, + 1,122,23,95,78,97,109,101,115,112,97,99,101,80,97,116, + 104,46,95,95,114,101,112,114,95,95,99,2,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, + 12,0,0,0,124,1,124,0,160,0,161,0,107,6,83,0, + 41,1,78,41,1,114,242,0,0,0,41,2,114,102,0,0, + 0,218,4,105,116,101,109,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,218,12,95,95,99,111,110,116,97,105, + 110,115,95,95,70,4,0,0,115,2,0,0,0,0,1,122, + 27,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, + 95,95,99,111,110,116,97,105,110,115,95,95,99,2,0,0, + 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, + 0,115,16,0,0,0,124,0,106,0,160,1,124,1,161,1, + 1,0,100,0,83,0,41,1,78,41,2,114,234,0,0,0, + 114,165,0,0,0,41,2,114,102,0,0,0,114,249,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,165,0,0,0,73,4,0,0,115,2,0,0,0,0,1, + 122,21,95,78,97,109,101,115,112,97,99,101,80,97,116,104, + 46,97,112,112,101,110,100,78,41,14,114,107,0,0,0,114, + 106,0,0,0,114,108,0,0,0,114,109,0,0,0,114,186, + 0,0,0,114,240,0,0,0,114,235,0,0,0,114,242,0, + 0,0,114,244,0,0,0,114,246,0,0,0,114,247,0,0, + 0,114,248,0,0,0,114,250,0,0,0,114,165,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,232,0,0,0,18,4,0,0,115,20,0, + 0,0,12,7,8,6,8,10,8,4,8,13,8,3,8,3, + 8,3,8,3,8,3,114,232,0,0,0,99,0,0,0,0, + 0,0,0,0,0,0,0,0,3,0,0,0,64,0,0,0, + 115,80,0,0,0,101,0,90,1,100,0,90,2,100,1,100, + 2,132,0,90,3,101,4,100,3,100,4,132,0,131,1,90, + 5,100,5,100,6,132,0,90,6,100,7,100,8,132,0,90, + 7,100,9,100,10,132,0,90,8,100,11,100,12,132,0,90, + 9,100,13,100,14,132,0,90,10,100,15,100,16,132,0,90, + 11,100,17,83,0,41,18,218,16,95,78,97,109,101,115,112, + 97,99,101,76,111,97,100,101,114,99,4,0,0,0,0,0, + 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,18, + 0,0,0,116,0,124,1,124,2,124,3,131,3,124,0,95, + 1,100,0,83,0,41,1,78,41,2,114,232,0,0,0,114, + 234,0,0,0,41,4,114,102,0,0,0,114,100,0,0,0, + 114,35,0,0,0,114,238,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,186,0,0,0,79,4, + 0,0,115,2,0,0,0,0,1,122,25,95,78,97,109,101, + 115,112,97,99,101,76,111,97,100,101,114,46,95,95,105,110, + 105,116,95,95,99,2,0,0,0,0,0,0,0,2,0,0, + 0,3,0,0,0,67,0,0,0,115,12,0,0,0,100,1, + 160,0,124,1,106,1,161,1,83,0,41,2,122,115,82,101, + 116,117,114,110,32,114,101,112,114,32,102,111,114,32,116,104, + 101,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, + 32,32,32,84,104,101,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,32,32,84,104, + 101,32,105,109,112,111,114,116,32,109,97,99,104,105,110,101, + 114,121,32,100,111,101,115,32,116,104,101,32,106,111,98,32, + 105,116,115,101,108,102,46,10,10,32,32,32,32,32,32,32, + 32,122,25,60,109,111,100,117,108,101,32,123,33,114,125,32, + 40,110,97,109,101,115,112,97,99,101,41,62,41,2,114,48, + 0,0,0,114,107,0,0,0,41,2,114,172,0,0,0,114, + 191,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,218,11,109,111,100,117,108,101,95,114,101,112,114, + 82,4,0,0,115,2,0,0,0,0,7,122,28,95,78,97, + 109,101,115,112,97,99,101,76,111,97,100,101,114,46,109,111, + 100,117,108,101,95,114,101,112,114,99,2,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, + 0,0,0,100,1,83,0,41,2,78,84,114,2,0,0,0, + 41,2,114,102,0,0,0,114,121,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,161,0,0,0, + 91,4,0,0,115,2,0,0,0,0,1,122,27,95,78,97, + 109,101,115,112,97,99,101,76,111,97,100,101,114,46,105,115, + 95,112,97,99,107,97,103,101,99,2,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,115,4,0, + 0,0,100,1,83,0,41,2,78,114,30,0,0,0,114,2, + 0,0,0,41,2,114,102,0,0,0,114,121,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,202, + 0,0,0,94,4,0,0,115,2,0,0,0,0,1,122,27, + 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,6,0,0,0,67,0,0,0, + 115,16,0,0,0,116,0,100,1,100,2,100,3,100,4,100, + 5,141,4,83,0,41,6,78,114,30,0,0,0,122,8,60, + 115,116,114,105,110,103,62,114,190,0,0,0,84,41,1,114, + 204,0,0,0,41,1,114,205,0,0,0,41,2,114,102,0, + 0,0,114,121,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,188,0,0,0,97,4,0,0,115, + 2,0,0,0,0,1,122,25,95,78,97,109,101,115,112,97, + 99,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, + 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, + 2,122,42,85,115,101,32,100,101,102,97,117,108,116,32,115, + 101,109,97,110,116,105,99,115,32,102,111,114,32,109,111,100, + 117,108,101,32,99,114,101,97,116,105,111,110,46,78,114,2, + 0,0,0,41,2,114,102,0,0,0,114,166,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,187, + 0,0,0,100,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,1,83,0,41,2,78,114,30,0, - 0,0,114,2,0,0,0,41,2,114,102,0,0,0,114,121, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,202,0,0,0,94,4,0,0,115,2,0,0,0, - 0,1,122,27,95,78,97,109,101,115,112,97,99,101,76,111, - 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,6,0,0,0, - 67,0,0,0,115,16,0,0,0,116,0,100,1,100,2,100, - 3,100,4,100,5,141,4,83,0,41,6,78,114,30,0,0, - 0,122,8,60,115,116,114,105,110,103,62,114,190,0,0,0, - 84,41,1,114,204,0,0,0,41,1,114,205,0,0,0,41, - 2,114,102,0,0,0,114,121,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,188,0,0,0,97, - 4,0,0,115,2,0,0,0,0,1,122,25,95,78,97,109, - 101,115,112,97,99,101,76,111,97,100,101,114,46,103,101,116, - 95,99,111,100,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, - 1,83,0,41,2,122,42,85,115,101,32,100,101,102,97,117, - 108,116,32,115,101,109,97,110,116,105,99,115,32,102,111,114, - 32,109,111,100,117,108,101,32,99,114,101,97,116,105,111,110, - 46,78,114,2,0,0,0,41,2,114,102,0,0,0,114,166, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,187,0,0,0,100,4,0,0,115,0,0,0,0, - 122,30,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,99,114,101,97,116,101,95,109,111,100,117,108,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, - 0,67,0,0,0,115,4,0,0,0,100,0,83,0,41,1, - 78,114,2,0,0,0,41,2,114,102,0,0,0,114,191,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,192,0,0,0,103,4,0,0,115,2,0,0,0,0, - 1,122,28,95,78,97,109,101,115,112,97,99,101,76,111,97, - 100,101,114,46,101,120,101,99,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 67,0,0,0,115,26,0,0,0,116,0,160,1,100,1,124, - 0,106,2,161,2,1,0,116,0,160,3,124,0,124,1,161, - 2,83,0,41,2,122,98,76,111,97,100,32,97,32,110,97, - 109,101,115,112,97,99,101,32,109,111,100,117,108,101,46,10, - 10,32,32,32,32,32,32,32,32,84,104,105,115,32,109,101, - 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, - 101,100,46,32,32,85,115,101,32,101,120,101,99,95,109,111, - 100,117,108,101,40,41,32,105,110,115,116,101,97,100,46,10, - 10,32,32,32,32,32,32,32,32,122,38,110,97,109,101,115, - 112,97,99,101,32,109,111,100,117,108,101,32,108,111,97,100, - 101,100,32,119,105,116,104,32,112,97,116,104,32,123,33,114, - 125,41,4,114,116,0,0,0,114,130,0,0,0,114,234,0, - 0,0,114,193,0,0,0,41,2,114,102,0,0,0,114,121, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,194,0,0,0,106,4,0,0,115,6,0,0,0, - 0,7,6,1,8,1,122,28,95,78,97,109,101,115,112,97, - 99,101,76,111,97,100,101,114,46,108,111,97,100,95,109,111, - 100,117,108,101,78,41,12,114,107,0,0,0,114,106,0,0, - 0,114,108,0,0,0,114,186,0,0,0,114,184,0,0,0, - 114,252,0,0,0,114,161,0,0,0,114,202,0,0,0,114, - 188,0,0,0,114,187,0,0,0,114,192,0,0,0,114,194, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,251,0,0,0,78,4,0,0, - 115,16,0,0,0,8,1,8,3,12,9,8,3,8,3,8, - 3,8,3,8,3,114,251,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,90,1,100,0,90,2,100,1,90,3, - 101,4,100,2,100,3,132,0,131,1,90,5,101,4,100,4, - 100,5,132,0,131,1,90,6,101,4,100,6,100,7,132,0, - 131,1,90,7,101,4,100,8,100,9,132,0,131,1,90,8, - 101,4,100,17,100,11,100,12,132,1,131,1,90,9,101,4, - 100,18,100,13,100,14,132,1,131,1,90,10,101,4,100,19, - 100,15,100,16,132,1,131,1,90,11,100,10,83,0,41,20, - 218,10,80,97,116,104,70,105,110,100,101,114,122,62,77,101, - 116,97,32,112,97,116,104,32,102,105,110,100,101,114,32,102, - 111,114,32,115,121,115,46,112,97,116,104,32,97,110,100,32, - 112,97,99,107,97,103,101,32,95,95,112,97,116,104,95,95, - 32,97,116,116,114,105,98,117,116,101,115,46,99,1,0,0, - 0,0,0,0,0,2,0,0,0,4,0,0,0,67,0,0, - 0,115,42,0,0,0,120,36,116,0,106,1,160,2,161,0, - 68,0,93,22,125,1,116,3,124,1,100,1,131,2,114,12, - 124,1,160,4,161,0,1,0,113,12,87,0,100,2,83,0, - 41,3,122,125,67,97,108,108,32,116,104,101,32,105,110,118, - 97,108,105,100,97,116,101,95,99,97,99,104,101,115,40,41, - 32,109,101,116,104,111,100,32,111,110,32,97,108,108,32,112, - 97,116,104,32,101,110,116,114,121,32,102,105,110,100,101,114, - 115,10,32,32,32,32,32,32,32,32,115,116,111,114,101,100, - 32,105,110,32,115,121,115,46,112,97,116,104,95,105,109,112, - 111,114,116,101,114,95,99,97,99,104,101,115,32,40,119,104, - 101,114,101,32,105,109,112,108,101,109,101,110,116,101,100,41, - 46,218,17,105,110,118,97,108,105,100,97,116,101,95,99,97, - 99,104,101,115,78,41,5,114,6,0,0,0,218,19,112,97, - 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, - 101,218,6,118,97,108,117,101,115,114,110,0,0,0,114,254, - 0,0,0,41,2,114,172,0,0,0,218,6,102,105,110,100, - 101,114,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,254,0,0,0,124,4,0,0,115,6,0,0,0,0, - 4,16,1,10,1,122,28,80,97,116,104,70,105,110,100,101, - 114,46,105,110,118,97,108,105,100,97,116,101,95,99,97,99, - 104,101,115,99,2,0,0,0,0,0,0,0,3,0,0,0, - 12,0,0,0,67,0,0,0,115,84,0,0,0,116,0,106, - 1,100,1,107,9,114,28,116,0,106,1,115,28,116,2,160, - 3,100,2,116,4,161,2,1,0,120,50,116,0,106,1,68, - 0,93,36,125,2,121,8,124,2,124,1,131,1,83,0,4, - 0,116,5,107,10,114,70,1,0,1,0,1,0,119,36,89, - 0,113,36,88,0,113,36,87,0,100,1,83,0,100,1,83, - 0,41,3,122,46,83,101,97,114,99,104,32,115,121,115,46, - 112,97,116,104,95,104,111,111,107,115,32,102,111,114,32,97, - 32,102,105,110,100,101,114,32,102,111,114,32,39,112,97,116, - 104,39,46,78,122,23,115,121,115,46,112,97,116,104,95,104, - 111,111,107,115,32,105,115,32,101,109,112,116,121,41,6,114, - 6,0,0,0,218,10,112,97,116,104,95,104,111,111,107,115, - 114,61,0,0,0,114,62,0,0,0,114,120,0,0,0,114, - 101,0,0,0,41,3,114,172,0,0,0,114,35,0,0,0, - 90,4,104,111,111,107,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,11,95,112,97,116,104,95,104,111,111, - 107,115,132,4,0,0,115,16,0,0,0,0,3,16,1,12, - 1,12,1,2,1,8,1,14,1,12,2,122,22,80,97,116, - 104,70,105,110,100,101,114,46,95,112,97,116,104,95,104,111, - 111,107,115,99,2,0,0,0,0,0,0,0,3,0,0,0, - 19,0,0,0,67,0,0,0,115,102,0,0,0,124,1,100, - 1,107,2,114,42,121,12,116,0,160,1,161,0,125,1,87, - 0,110,20,4,0,116,2,107,10,114,40,1,0,1,0,1, - 0,100,2,83,0,88,0,121,14,116,3,106,4,124,1,25, - 0,125,2,87,0,110,40,4,0,116,5,107,10,114,96,1, - 0,1,0,1,0,124,0,160,6,124,1,161,1,125,2,124, - 2,116,3,106,4,124,1,60,0,89,0,110,2,88,0,124, - 2,83,0,41,3,122,210,71,101,116,32,116,104,101,32,102, - 105,110,100,101,114,32,102,111,114,32,116,104,101,32,112,97, - 116,104,32,101,110,116,114,121,32,102,114,111,109,32,115,121, - 115,46,112,97,116,104,95,105,109,112,111,114,116,101,114,95, - 99,97,99,104,101,46,10,10,32,32,32,32,32,32,32,32, - 73,102,32,116,104,101,32,112,97,116,104,32,101,110,116,114, - 121,32,105,115,32,110,111,116,32,105,110,32,116,104,101,32, - 99,97,99,104,101,44,32,102,105,110,100,32,116,104,101,32, - 97,112,112,114,111,112,114,105,97,116,101,32,102,105,110,100, - 101,114,10,32,32,32,32,32,32,32,32,97,110,100,32,99, - 97,99,104,101,32,105,116,46,32,73,102,32,110,111,32,102, - 105,110,100,101,114,32,105,115,32,97,118,97,105,108,97,98, - 108,101,44,32,115,116,111,114,101,32,78,111,110,101,46,10, - 10,32,32,32,32,32,32,32,32,114,30,0,0,0,78,41, - 7,114,1,0,0,0,114,45,0,0,0,218,17,70,105,108, - 101,78,111,116,70,111,117,110,100,69,114,114,111,114,114,6, - 0,0,0,114,255,0,0,0,218,8,75,101,121,69,114,114, - 111,114,114,3,1,0,0,41,3,114,172,0,0,0,114,35, - 0,0,0,114,1,1,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,20,95,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,145,4,0, - 0,115,22,0,0,0,0,8,8,1,2,1,12,1,14,3, - 6,1,2,1,14,1,14,1,10,1,16,1,122,31,80,97, - 116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,99,3,0, - 0,0,0,0,0,0,6,0,0,0,4,0,0,0,67,0, - 0,0,115,82,0,0,0,116,0,124,2,100,1,131,2,114, - 26,124,2,160,1,124,1,161,1,92,2,125,3,125,4,110, - 14,124,2,160,2,124,1,161,1,125,3,103,0,125,4,124, - 3,100,0,107,9,114,60,116,3,160,4,124,1,124,3,161, - 2,83,0,116,3,160,5,124,1,100,0,161,2,125,5,124, - 4,124,5,95,6,124,5,83,0,41,2,78,114,119,0,0, - 0,41,7,114,110,0,0,0,114,119,0,0,0,114,183,0, - 0,0,114,116,0,0,0,114,180,0,0,0,114,162,0,0, - 0,114,158,0,0,0,41,6,114,172,0,0,0,114,121,0, - 0,0,114,1,1,0,0,114,122,0,0,0,114,123,0,0, - 0,114,166,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,16,95,108,101,103,97,99,121,95,103, - 101,116,95,115,112,101,99,167,4,0,0,115,18,0,0,0, - 0,4,10,1,16,2,10,1,4,1,8,1,12,1,12,1, - 6,1,122,27,80,97,116,104,70,105,110,100,101,114,46,95, - 108,101,103,97,99,121,95,103,101,116,95,115,112,101,99,78, - 99,4,0,0,0,0,0,0,0,9,0,0,0,5,0,0, - 0,67,0,0,0,115,170,0,0,0,103,0,125,4,120,160, - 124,2,68,0,93,130,125,5,116,0,124,5,116,1,116,2, - 102,2,131,2,115,30,113,10,124,0,160,3,124,5,161,1, - 125,6,124,6,100,1,107,9,114,10,116,4,124,6,100,2, - 131,2,114,72,124,6,160,5,124,1,124,3,161,2,125,7, - 110,12,124,0,160,6,124,1,124,6,161,2,125,7,124,7, - 100,1,107,8,114,94,113,10,124,7,106,7,100,1,107,9, - 114,108,124,7,83,0,124,7,106,8,125,8,124,8,100,1, - 107,8,114,130,116,9,100,3,131,1,130,1,124,4,160,10, - 124,8,161,1,1,0,113,10,87,0,116,11,160,12,124,1, - 100,1,161,2,125,7,124,4,124,7,95,8,124,7,83,0, - 100,1,83,0,41,4,122,63,70,105,110,100,32,116,104,101, - 32,108,111,97,100,101,114,32,111,114,32,110,97,109,101,115, - 112,97,99,101,95,112,97,116,104,32,102,111,114,32,116,104, - 105,115,32,109,111,100,117,108,101,47,112,97,99,107,97,103, - 101,32,110,97,109,101,46,78,114,182,0,0,0,122,19,115, - 112,101,99,32,109,105,115,115,105,110,103,32,108,111,97,100, - 101,114,41,13,114,141,0,0,0,114,71,0,0,0,218,5, - 98,121,116,101,115,114,6,1,0,0,114,110,0,0,0,114, - 182,0,0,0,114,7,1,0,0,114,122,0,0,0,114,158, - 0,0,0,114,101,0,0,0,114,147,0,0,0,114,116,0, - 0,0,114,162,0,0,0,41,9,114,172,0,0,0,114,121, - 0,0,0,114,35,0,0,0,114,181,0,0,0,218,14,110, - 97,109,101,115,112,97,99,101,95,112,97,116,104,90,5,101, - 110,116,114,121,114,1,1,0,0,114,166,0,0,0,114,123, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,9,95,103,101,116,95,115,112,101,99,182,4,0, - 0,115,40,0,0,0,0,5,4,1,10,1,14,1,2,1, - 10,1,8,1,10,1,14,2,12,1,8,1,2,1,10,1, - 4,1,6,1,8,1,8,5,14,2,12,1,6,1,122,20, - 80,97,116,104,70,105,110,100,101,114,46,95,103,101,116,95, - 115,112,101,99,99,4,0,0,0,0,0,0,0,6,0,0, - 0,5,0,0,0,67,0,0,0,115,100,0,0,0,124,2, - 100,1,107,8,114,14,116,0,106,1,125,2,124,0,160,2, - 124,1,124,2,124,3,161,3,125,4,124,4,100,1,107,8, - 114,40,100,1,83,0,124,4,106,3,100,1,107,8,114,92, - 124,4,106,4,125,5,124,5,114,86,100,2,124,4,95,5, - 116,6,124,1,124,5,124,0,106,2,131,3,124,4,95,4, - 124,4,83,0,100,1,83,0,110,4,124,4,83,0,100,1, - 83,0,41,3,122,141,84,114,121,32,116,111,32,102,105,110, - 100,32,97,32,115,112,101,99,32,102,111,114,32,39,102,117, - 108,108,110,97,109,101,39,32,111,110,32,115,121,115,46,112, - 97,116,104,32,111,114,32,39,112,97,116,104,39,46,10,10, - 32,32,32,32,32,32,32,32,84,104,101,32,115,101,97,114, - 99,104,32,105,115,32,98,97,115,101,100,32,111,110,32,115, - 121,115,46,112,97,116,104,95,104,111,111,107,115,32,97,110, - 100,32,115,121,115,46,112,97,116,104,95,105,109,112,111,114, - 116,101,114,95,99,97,99,104,101,46,10,32,32,32,32,32, - 32,32,32,78,90,9,110,97,109,101,115,112,97,99,101,41, - 7,114,6,0,0,0,114,35,0,0,0,114,10,1,0,0, - 114,122,0,0,0,114,158,0,0,0,114,160,0,0,0,114, - 232,0,0,0,41,6,114,172,0,0,0,114,121,0,0,0, - 114,35,0,0,0,114,181,0,0,0,114,166,0,0,0,114, - 9,1,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,182,0,0,0,214,4,0,0,115,26,0,0, - 0,0,6,8,1,6,1,14,1,8,1,4,1,10,1,6, - 1,4,3,6,1,16,1,4,2,6,2,122,20,80,97,116, - 104,70,105,110,100,101,114,46,102,105,110,100,95,115,112,101, - 99,99,3,0,0,0,0,0,0,0,4,0,0,0,4,0, - 0,0,67,0,0,0,115,30,0,0,0,124,0,160,0,124, - 1,124,2,161,2,125,3,124,3,100,1,107,8,114,24,100, - 1,83,0,124,3,106,1,83,0,41,2,122,170,102,105,110, - 100,32,116,104,101,32,109,111,100,117,108,101,32,111,110,32, - 115,121,115,46,112,97,116,104,32,111,114,32,39,112,97,116, - 104,39,32,98,97,115,101,100,32,111,110,32,115,121,115,46, - 112,97,116,104,95,104,111,111,107,115,32,97,110,100,10,32, - 32,32,32,32,32,32,32,115,121,115,46,112,97,116,104,95, - 105,109,112,111,114,116,101,114,95,99,97,99,104,101,46,10, - 10,32,32,32,32,32,32,32,32,84,104,105,115,32,109,101, - 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, - 101,100,46,32,32,85,115,101,32,102,105,110,100,95,115,112, - 101,99,40,41,32,105,110,115,116,101,97,100,46,10,10,32, - 32,32,32,32,32,32,32,78,41,2,114,182,0,0,0,114, - 122,0,0,0,41,4,114,172,0,0,0,114,121,0,0,0, - 114,35,0,0,0,114,166,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,183,0,0,0,238,4, - 0,0,115,8,0,0,0,0,8,12,1,8,1,4,1,122, - 22,80,97,116,104,70,105,110,100,101,114,46,102,105,110,100, - 95,109,111,100,117,108,101,41,1,78,41,2,78,78,41,1, + 0,115,4,0,0,0,100,0,83,0,41,1,78,114,2,0, + 0,0,41,2,114,102,0,0,0,114,191,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,192,0, + 0,0,103,4,0,0,115,2,0,0,0,0,1,122,28,95, + 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, + 101,120,101,99,95,109,111,100,117,108,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, + 115,26,0,0,0,116,0,160,1,100,1,124,0,106,2,161, + 2,1,0,116,0,160,3,124,0,124,1,161,2,83,0,41, + 2,122,98,76,111,97,100,32,97,32,110,97,109,101,115,112, + 97,99,101,32,109,111,100,117,108,101,46,10,10,32,32,32, + 32,32,32,32,32,84,104,105,115,32,109,101,116,104,111,100, + 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, + 32,85,115,101,32,101,120,101,99,95,109,111,100,117,108,101, + 40,41,32,105,110,115,116,101,97,100,46,10,10,32,32,32, + 32,32,32,32,32,122,38,110,97,109,101,115,112,97,99,101, + 32,109,111,100,117,108,101,32,108,111,97,100,101,100,32,119, + 105,116,104,32,112,97,116,104,32,123,33,114,125,41,4,114, + 116,0,0,0,114,130,0,0,0,114,234,0,0,0,114,193, + 0,0,0,41,2,114,102,0,0,0,114,121,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,194, + 0,0,0,106,4,0,0,115,6,0,0,0,0,7,6,1, + 8,1,122,28,95,78,97,109,101,115,112,97,99,101,76,111, + 97,100,101,114,46,108,111,97,100,95,109,111,100,117,108,101, 78,41,12,114,107,0,0,0,114,106,0,0,0,114,108,0, - 0,0,114,109,0,0,0,114,184,0,0,0,114,254,0,0, - 0,114,3,1,0,0,114,6,1,0,0,114,7,1,0,0, - 114,10,1,0,0,114,182,0,0,0,114,183,0,0,0,114, + 0,0,114,186,0,0,0,114,184,0,0,0,114,252,0,0, + 0,114,161,0,0,0,114,202,0,0,0,114,188,0,0,0, + 114,187,0,0,0,114,192,0,0,0,114,194,0,0,0,114, 2,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,253,0,0,0,120,4,0,0,115,20,0,0, - 0,12,4,12,8,12,13,12,22,12,15,2,1,12,31,2, - 1,12,23,2,1,114,253,0,0,0,99,0,0,0,0,0, - 0,0,0,0,0,0,0,3,0,0,0,64,0,0,0,115, - 90,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, - 100,2,100,3,132,0,90,4,100,4,100,5,132,0,90,5, - 101,6,90,7,100,6,100,7,132,0,90,8,100,8,100,9, - 132,0,90,9,100,19,100,11,100,12,132,1,90,10,100,13, - 100,14,132,0,90,11,101,12,100,15,100,16,132,0,131,1, - 90,13,100,17,100,18,132,0,90,14,100,10,83,0,41,20, - 218,10,70,105,108,101,70,105,110,100,101,114,122,172,70,105, - 108,101,45,98,97,115,101,100,32,102,105,110,100,101,114,46, - 10,10,32,32,32,32,73,110,116,101,114,97,99,116,105,111, - 110,115,32,119,105,116,104,32,116,104,101,32,102,105,108,101, - 32,115,121,115,116,101,109,32,97,114,101,32,99,97,99,104, - 101,100,32,102,111,114,32,112,101,114,102,111,114,109,97,110, - 99,101,44,32,98,101,105,110,103,10,32,32,32,32,114,101, - 102,114,101,115,104,101,100,32,119,104,101,110,32,116,104,101, - 32,100,105,114,101,99,116,111,114,121,32,116,104,101,32,102, - 105,110,100,101,114,32,105,115,32,104,97,110,100,108,105,110, - 103,32,104,97,115,32,98,101,101,110,32,109,111,100,105,102, - 105,101,100,46,10,10,32,32,32,32,99,2,0,0,0,0, - 0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,115, - 88,0,0,0,103,0,125,3,120,40,124,2,68,0,93,32, - 92,2,137,0,125,4,124,3,160,0,135,0,102,1,100,1, - 100,2,132,8,124,4,68,0,131,1,161,1,1,0,113,10, - 87,0,124,3,124,0,95,1,124,1,112,58,100,3,124,0, - 95,2,100,4,124,0,95,3,116,4,131,0,124,0,95,5, - 116,4,131,0,124,0,95,6,100,5,83,0,41,6,122,154, - 73,110,105,116,105,97,108,105,122,101,32,119,105,116,104,32, - 116,104,101,32,112,97,116,104,32,116,111,32,115,101,97,114, - 99,104,32,111,110,32,97,110,100,32,97,32,118,97,114,105, - 97,98,108,101,32,110,117,109,98,101,114,32,111,102,10,32, - 32,32,32,32,32,32,32,50,45,116,117,112,108,101,115,32, - 99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,108, - 111,97,100,101,114,32,97,110,100,32,116,104,101,32,102,105, - 108,101,32,115,117,102,102,105,120,101,115,32,116,104,101,32, - 108,111,97,100,101,114,10,32,32,32,32,32,32,32,32,114, - 101,99,111,103,110,105,122,101,115,46,99,1,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,51,0,0,0,115, - 22,0,0,0,124,0,93,14,125,1,124,1,136,0,102,2, - 86,0,1,0,113,2,100,0,83,0,41,1,78,114,2,0, - 0,0,41,2,114,22,0,0,0,114,227,0,0,0,41,1, - 114,122,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 229,0,0,0,11,5,0,0,115,2,0,0,0,4,0,122, - 38,70,105,108,101,70,105,110,100,101,114,46,95,95,105,110, - 105,116,95,95,46,60,108,111,99,97,108,115,62,46,60,103, - 101,110,101,120,112,114,62,114,59,0,0,0,114,89,0,0, - 0,78,41,7,114,147,0,0,0,218,8,95,108,111,97,100, - 101,114,115,114,35,0,0,0,218,11,95,112,97,116,104,95, - 109,116,105,109,101,218,3,115,101,116,218,11,95,112,97,116, - 104,95,99,97,99,104,101,218,19,95,114,101,108,97,120,101, - 100,95,112,97,116,104,95,99,97,99,104,101,41,5,114,102, - 0,0,0,114,35,0,0,0,218,14,108,111,97,100,101,114, - 95,100,101,116,97,105,108,115,90,7,108,111,97,100,101,114, - 115,114,168,0,0,0,114,2,0,0,0,41,1,114,122,0, - 0,0,114,4,0,0,0,114,186,0,0,0,5,5,0,0, - 115,16,0,0,0,0,4,4,1,14,1,28,1,6,2,10, - 1,6,1,8,1,122,19,70,105,108,101,70,105,110,100,101, - 114,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, - 0,0,0,1,0,0,0,2,0,0,0,67,0,0,0,115, - 10,0,0,0,100,1,124,0,95,0,100,2,83,0,41,3, - 122,31,73,110,118,97,108,105,100,97,116,101,32,116,104,101, - 32,100,105,114,101,99,116,111,114,121,32,109,116,105,109,101, - 46,114,89,0,0,0,78,41,1,114,13,1,0,0,41,1, - 114,102,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,254,0,0,0,19,5,0,0,115,2,0, - 0,0,0,2,122,28,70,105,108,101,70,105,110,100,101,114, - 46,105,110,118,97,108,105,100,97,116,101,95,99,97,99,104, - 101,115,99,2,0,0,0,0,0,0,0,3,0,0,0,3, - 0,0,0,67,0,0,0,115,42,0,0,0,124,0,160,0, - 124,1,161,1,125,2,124,2,100,1,107,8,114,26,100,1, - 103,0,102,2,83,0,124,2,106,1,124,2,106,2,112,38, - 103,0,102,2,83,0,41,2,122,197,84,114,121,32,116,111, - 32,102,105,110,100,32,97,32,108,111,97,100,101,114,32,102, - 111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100, - 32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,32, - 110,97,109,101,115,112,97,99,101,10,32,32,32,32,32,32, - 32,32,112,97,99,107,97,103,101,32,112,111,114,116,105,111, - 110,115,46,32,82,101,116,117,114,110,115,32,40,108,111,97, - 100,101,114,44,32,108,105,115,116,45,111,102,45,112,111,114, - 116,105,111,110,115,41,46,10,10,32,32,32,32,32,32,32, - 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, - 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, - 32,102,105,110,100,95,115,112,101,99,40,41,32,105,110,115, - 116,101,97,100,46,10,10,32,32,32,32,32,32,32,32,78, - 41,3,114,182,0,0,0,114,122,0,0,0,114,158,0,0, - 0,41,3,114,102,0,0,0,114,121,0,0,0,114,166,0, + 0,0,0,114,251,0,0,0,78,4,0,0,115,16,0,0, + 0,8,1,8,3,12,9,8,3,8,3,8,3,8,3,8, + 3,114,251,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,90,1,100,0,90,2,100,1,90,3,101,4,100,2, + 100,3,132,0,131,1,90,5,101,4,100,4,100,5,132,0, + 131,1,90,6,101,4,100,6,100,7,132,0,131,1,90,7, + 101,4,100,8,100,9,132,0,131,1,90,8,101,4,100,17, + 100,11,100,12,132,1,131,1,90,9,101,4,100,18,100,13, + 100,14,132,1,131,1,90,10,101,4,100,19,100,15,100,16, + 132,1,131,1,90,11,100,10,83,0,41,20,218,10,80,97, + 116,104,70,105,110,100,101,114,122,62,77,101,116,97,32,112, + 97,116,104,32,102,105,110,100,101,114,32,102,111,114,32,115, + 121,115,46,112,97,116,104,32,97,110,100,32,112,97,99,107, + 97,103,101,32,95,95,112,97,116,104,95,95,32,97,116,116, + 114,105,98,117,116,101,115,46,99,1,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,67,0,0,0,115,42,0, + 0,0,120,36,116,0,106,1,160,2,161,0,68,0,93,22, + 125,1,116,3,124,1,100,1,131,2,114,12,124,1,160,4, + 161,0,1,0,113,12,87,0,100,2,83,0,41,3,122,125, + 67,97,108,108,32,116,104,101,32,105,110,118,97,108,105,100, + 97,116,101,95,99,97,99,104,101,115,40,41,32,109,101,116, + 104,111,100,32,111,110,32,97,108,108,32,112,97,116,104,32, + 101,110,116,114,121,32,102,105,110,100,101,114,115,10,32,32, + 32,32,32,32,32,32,115,116,111,114,101,100,32,105,110,32, + 115,121,115,46,112,97,116,104,95,105,109,112,111,114,116,101, + 114,95,99,97,99,104,101,115,32,40,119,104,101,114,101,32, + 105,109,112,108,101,109,101,110,116,101,100,41,46,218,17,105, + 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, + 78,41,5,114,6,0,0,0,218,19,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,218,6,118, + 97,108,117,101,115,114,110,0,0,0,114,254,0,0,0,41, + 2,114,172,0,0,0,218,6,102,105,110,100,101,114,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,254,0, + 0,0,124,4,0,0,115,6,0,0,0,0,4,16,1,10, + 1,122,28,80,97,116,104,70,105,110,100,101,114,46,105,110, + 118,97,108,105,100,97,116,101,95,99,97,99,104,101,115,99, + 2,0,0,0,0,0,0,0,3,0,0,0,12,0,0,0, + 67,0,0,0,115,84,0,0,0,116,0,106,1,100,1,107, + 9,114,28,116,0,106,1,115,28,116,2,160,3,100,2,116, + 4,161,2,1,0,120,50,116,0,106,1,68,0,93,36,125, + 2,121,8,124,2,124,1,131,1,83,0,4,0,116,5,107, + 10,114,70,1,0,1,0,1,0,119,36,89,0,113,36,88, + 0,113,36,87,0,100,1,83,0,100,1,83,0,41,3,122, + 46,83,101,97,114,99,104,32,115,121,115,46,112,97,116,104, + 95,104,111,111,107,115,32,102,111,114,32,97,32,102,105,110, + 100,101,114,32,102,111,114,32,39,112,97,116,104,39,46,78, + 122,23,115,121,115,46,112,97,116,104,95,104,111,111,107,115, + 32,105,115,32,101,109,112,116,121,41,6,114,6,0,0,0, + 218,10,112,97,116,104,95,104,111,111,107,115,114,61,0,0, + 0,114,62,0,0,0,114,120,0,0,0,114,101,0,0,0, + 41,3,114,172,0,0,0,114,35,0,0,0,90,4,104,111, + 111,107,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,11,95,112,97,116,104,95,104,111,111,107,115,132,4, + 0,0,115,16,0,0,0,0,3,16,1,12,1,12,1,2, + 1,8,1,14,1,12,2,122,22,80,97,116,104,70,105,110, + 100,101,114,46,95,112,97,116,104,95,104,111,111,107,115,99, + 2,0,0,0,0,0,0,0,3,0,0,0,19,0,0,0, + 67,0,0,0,115,102,0,0,0,124,1,100,1,107,2,114, + 42,121,12,116,0,160,1,161,0,125,1,87,0,110,20,4, + 0,116,2,107,10,114,40,1,0,1,0,1,0,100,2,83, + 0,88,0,121,14,116,3,106,4,124,1,25,0,125,2,87, + 0,110,40,4,0,116,5,107,10,114,96,1,0,1,0,1, + 0,124,0,160,6,124,1,161,1,125,2,124,2,116,3,106, + 4,124,1,60,0,89,0,110,2,88,0,124,2,83,0,41, + 3,122,210,71,101,116,32,116,104,101,32,102,105,110,100,101, + 114,32,102,111,114,32,116,104,101,32,112,97,116,104,32,101, + 110,116,114,121,32,102,114,111,109,32,115,121,115,46,112,97, + 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, + 101,46,10,10,32,32,32,32,32,32,32,32,73,102,32,116, + 104,101,32,112,97,116,104,32,101,110,116,114,121,32,105,115, + 32,110,111,116,32,105,110,32,116,104,101,32,99,97,99,104, + 101,44,32,102,105,110,100,32,116,104,101,32,97,112,112,114, + 111,112,114,105,97,116,101,32,102,105,110,100,101,114,10,32, + 32,32,32,32,32,32,32,97,110,100,32,99,97,99,104,101, + 32,105,116,46,32,73,102,32,110,111,32,102,105,110,100,101, + 114,32,105,115,32,97,118,97,105,108,97,98,108,101,44,32, + 115,116,111,114,101,32,78,111,110,101,46,10,10,32,32,32, + 32,32,32,32,32,114,30,0,0,0,78,41,7,114,1,0, + 0,0,114,45,0,0,0,218,17,70,105,108,101,78,111,116, + 70,111,117,110,100,69,114,114,111,114,114,6,0,0,0,114, + 255,0,0,0,218,8,75,101,121,69,114,114,111,114,114,3, + 1,0,0,41,3,114,172,0,0,0,114,35,0,0,0,114, + 1,1,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,218,20,95,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,145,4,0,0,115,22,0, + 0,0,0,8,8,1,2,1,12,1,14,3,6,1,2,1, + 14,1,14,1,10,1,16,1,122,31,80,97,116,104,70,105, + 110,100,101,114,46,95,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,99,3,0,0,0,0,0, + 0,0,6,0,0,0,4,0,0,0,67,0,0,0,115,82, + 0,0,0,116,0,124,2,100,1,131,2,114,26,124,2,160, + 1,124,1,161,1,92,2,125,3,125,4,110,14,124,2,160, + 2,124,1,161,1,125,3,103,0,125,4,124,3,100,0,107, + 9,114,60,116,3,160,4,124,1,124,3,161,2,83,0,116, + 3,160,5,124,1,100,0,161,2,125,5,124,4,124,5,95, + 6,124,5,83,0,41,2,78,114,119,0,0,0,41,7,114, + 110,0,0,0,114,119,0,0,0,114,183,0,0,0,114,116, + 0,0,0,114,180,0,0,0,114,162,0,0,0,114,158,0, + 0,0,41,6,114,172,0,0,0,114,121,0,0,0,114,1, + 1,0,0,114,122,0,0,0,114,123,0,0,0,114,166,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,119,0,0,0,25,5,0,0,115,8,0,0,0,0, - 7,10,1,8,1,8,1,122,22,70,105,108,101,70,105,110, - 100,101,114,46,102,105,110,100,95,108,111,97,100,101,114,99, - 6,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0, - 67,0,0,0,115,26,0,0,0,124,1,124,2,124,3,131, - 2,125,6,116,0,124,2,124,3,124,6,124,4,100,1,141, - 4,83,0,41,2,78,41,2,114,122,0,0,0,114,158,0, - 0,0,41,1,114,169,0,0,0,41,7,114,102,0,0,0, - 114,167,0,0,0,114,121,0,0,0,114,35,0,0,0,90, - 4,115,109,115,108,114,181,0,0,0,114,122,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,10, - 1,0,0,37,5,0,0,115,6,0,0,0,0,1,10,1, - 8,1,122,20,70,105,108,101,70,105,110,100,101,114,46,95, - 103,101,116,95,115,112,101,99,78,99,3,0,0,0,0,0, - 0,0,14,0,0,0,16,0,0,0,67,0,0,0,115,98, - 1,0,0,100,1,125,3,124,1,160,0,100,2,161,1,100, - 3,25,0,125,4,121,24,116,1,124,0,106,2,112,34,116, - 3,160,4,161,0,131,1,106,5,125,5,87,0,110,24,4, - 0,116,6,107,10,114,66,1,0,1,0,1,0,100,4,125, - 5,89,0,110,2,88,0,124,5,124,0,106,7,107,3,114, - 92,124,0,160,8,161,0,1,0,124,5,124,0,95,7,116, - 9,131,0,114,114,124,0,106,10,125,6,124,4,160,11,161, - 0,125,7,110,10,124,0,106,12,125,6,124,4,125,7,124, - 7,124,6,107,6,114,218,116,13,124,0,106,2,124,4,131, - 2,125,8,120,72,124,0,106,14,68,0,93,54,92,2,125, - 9,125,10,100,5,124,9,23,0,125,11,116,13,124,8,124, - 11,131,2,125,12,116,15,124,12,131,1,114,152,124,0,160, - 16,124,10,124,1,124,12,124,8,103,1,124,2,161,5,83, - 0,113,152,87,0,116,17,124,8,131,1,125,3,120,88,124, - 0,106,14,68,0,93,78,92,2,125,9,125,10,116,13,124, - 0,106,2,124,4,124,9,23,0,131,2,125,12,116,18,106, - 19,100,6,124,12,100,3,100,7,141,3,1,0,124,7,124, - 9,23,0,124,6,107,6,114,226,116,15,124,12,131,1,114, - 226,124,0,160,16,124,10,124,1,124,12,100,8,124,2,161, - 5,83,0,113,226,87,0,124,3,144,1,114,94,116,18,160, - 19,100,9,124,8,161,2,1,0,116,18,160,20,124,1,100, - 8,161,2,125,13,124,8,103,1,124,13,95,21,124,13,83, - 0,100,8,83,0,41,10,122,111,84,114,121,32,116,111,32, - 102,105,110,100,32,97,32,115,112,101,99,32,102,111,114,32, - 116,104,101,32,115,112,101,99,105,102,105,101,100,32,109,111, - 100,117,108,101,46,10,10,32,32,32,32,32,32,32,32,82, - 101,116,117,114,110,115,32,116,104,101,32,109,97,116,99,104, - 105,110,103,32,115,112,101,99,44,32,111,114,32,78,111,110, - 101,32,105,102,32,110,111,116,32,102,111,117,110,100,46,10, - 32,32,32,32,32,32,32,32,70,114,59,0,0,0,114,57, - 0,0,0,114,89,0,0,0,114,186,0,0,0,122,9,116, - 114,121,105,110,103,32,123,125,41,1,90,9,118,101,114,98, - 111,115,105,116,121,78,122,25,112,111,115,115,105,98,108,101, - 32,110,97,109,101,115,112,97,99,101,32,102,111,114,32,123, - 125,41,22,114,32,0,0,0,114,39,0,0,0,114,35,0, - 0,0,114,1,0,0,0,114,45,0,0,0,114,221,0,0, - 0,114,40,0,0,0,114,13,1,0,0,218,11,95,102,105, - 108,108,95,99,97,99,104,101,114,5,0,0,0,114,16,1, - 0,0,114,90,0,0,0,114,15,1,0,0,114,28,0,0, - 0,114,12,1,0,0,114,44,0,0,0,114,10,1,0,0, - 114,46,0,0,0,114,116,0,0,0,114,130,0,0,0,114, - 162,0,0,0,114,158,0,0,0,41,14,114,102,0,0,0, - 114,121,0,0,0,114,181,0,0,0,90,12,105,115,95,110, - 97,109,101,115,112,97,99,101,90,11,116,97,105,108,95,109, - 111,100,117,108,101,114,149,0,0,0,90,5,99,97,99,104, - 101,90,12,99,97,99,104,101,95,109,111,100,117,108,101,90, - 9,98,97,115,101,95,112,97,116,104,114,227,0,0,0,114, - 167,0,0,0,90,13,105,110,105,116,95,102,105,108,101,110, - 97,109,101,90,9,102,117,108,108,95,112,97,116,104,114,166, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,182,0,0,0,42,5,0,0,115,70,0,0,0, - 0,5,4,1,14,1,2,1,24,1,14,1,10,1,10,1, - 8,1,6,2,6,1,6,1,10,2,6,1,4,2,8,1, - 12,1,16,1,8,1,10,1,8,1,24,4,8,2,16,1, - 16,1,16,1,12,1,8,1,10,1,12,1,6,1,12,1, - 12,1,8,1,4,1,122,20,70,105,108,101,70,105,110,100, - 101,114,46,102,105,110,100,95,115,112,101,99,99,1,0,0, - 0,0,0,0,0,9,0,0,0,14,0,0,0,67,0,0, - 0,115,194,0,0,0,124,0,106,0,125,1,121,22,116,1, - 160,2,124,1,112,22,116,1,160,3,161,0,161,1,125,2, - 87,0,110,30,4,0,116,4,116,5,116,6,102,3,107,10, - 114,58,1,0,1,0,1,0,103,0,125,2,89,0,110,2, - 88,0,116,7,106,8,160,9,100,1,161,1,115,84,116,10, - 124,2,131,1,124,0,95,11,110,78,116,10,131,0,125,3, - 120,64,124,2,68,0,93,56,125,4,124,4,160,12,100,2, - 161,1,92,3,125,5,125,6,125,7,124,6,114,138,100,3, - 160,13,124,5,124,7,160,14,161,0,161,2,125,8,110,4, - 124,5,125,8,124,3,160,15,124,8,161,1,1,0,113,96, - 87,0,124,3,124,0,95,11,116,7,106,8,160,9,116,16, - 161,1,114,190,100,4,100,5,132,0,124,2,68,0,131,1, - 124,0,95,17,100,6,83,0,41,7,122,68,70,105,108,108, - 32,116,104,101,32,99,97,99,104,101,32,111,102,32,112,111, - 116,101,110,116,105,97,108,32,109,111,100,117,108,101,115,32, - 97,110,100,32,112,97,99,107,97,103,101,115,32,102,111,114, - 32,116,104,105,115,32,100,105,114,101,99,116,111,114,121,46, - 114,0,0,0,0,114,59,0,0,0,122,5,123,125,46,123, - 125,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,83,0,0,0,115,20,0,0,0,104,0,124,0,93, - 12,125,1,124,1,160,0,161,0,146,2,113,4,83,0,114, - 2,0,0,0,41,1,114,90,0,0,0,41,2,114,22,0, - 0,0,90,2,102,110,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,250,9,60,115,101,116,99,111,109,112,62, - 119,5,0,0,115,2,0,0,0,6,0,122,41,70,105,108, - 101,70,105,110,100,101,114,46,95,102,105,108,108,95,99,97, - 99,104,101,46,60,108,111,99,97,108,115,62,46,60,115,101, - 116,99,111,109,112,62,78,41,18,114,35,0,0,0,114,1, - 0,0,0,90,7,108,105,115,116,100,105,114,114,45,0,0, - 0,114,4,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,6,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,14,1,0,0,114, - 15,1,0,0,114,85,0,0,0,114,48,0,0,0,114,90, - 0,0,0,218,3,97,100,100,114,9,0,0,0,114,16,1, - 0,0,41,9,114,102,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, - 249,0,0,0,114,100,0,0,0,114,239,0,0,0,114,227, - 0,0,0,90,8,110,101,119,95,110,97,109,101,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,18,1,0, - 0,90,5,0,0,115,34,0,0,0,0,2,6,1,2,1, - 22,1,20,3,10,3,12,1,12,7,6,1,10,1,16,1, - 4,1,18,2,4,1,14,1,6,1,12,1,122,22,70,105, - 108,101,70,105,110,100,101,114,46,95,102,105,108,108,95,99, - 97,99,104,101,99,1,0,0,0,0,0,0,0,3,0,0, - 0,3,0,0,0,7,0,0,0,115,18,0,0,0,135,0, - 135,1,102,2,100,1,100,2,132,8,125,2,124,2,83,0, - 41,3,97,20,1,0,0,65,32,99,108,97,115,115,32,109, - 101,116,104,111,100,32,119,104,105,99,104,32,114,101,116,117, - 114,110,115,32,97,32,99,108,111,115,117,114,101,32,116,111, - 32,117,115,101,32,111,110,32,115,121,115,46,112,97,116,104, - 95,104,111,111,107,10,32,32,32,32,32,32,32,32,119,104, - 105,99,104,32,119,105,108,108,32,114,101,116,117,114,110,32, - 97,110,32,105,110,115,116,97,110,99,101,32,117,115,105,110, - 103,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, - 108,111,97,100,101,114,115,32,97,110,100,32,116,104,101,32, - 112,97,116,104,10,32,32,32,32,32,32,32,32,99,97,108, - 108,101,100,32,111,110,32,116,104,101,32,99,108,111,115,117, - 114,101,46,10,10,32,32,32,32,32,32,32,32,73,102,32, - 116,104,101,32,112,97,116,104,32,99,97,108,108,101,100,32, - 111,110,32,116,104,101,32,99,108,111,115,117,114,101,32,105, - 115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114, - 121,44,32,73,109,112,111,114,116,69,114,114,111,114,32,105, - 115,10,32,32,32,32,32,32,32,32,114,97,105,115,101,100, - 46,10,10,32,32,32,32,32,32,32,32,99,1,0,0,0, - 0,0,0,0,1,0,0,0,4,0,0,0,19,0,0,0, - 115,34,0,0,0,116,0,124,0,131,1,115,20,116,1,100, - 1,124,0,100,2,141,2,130,1,136,0,124,0,102,1,136, - 1,158,2,142,0,83,0,41,3,122,45,80,97,116,104,32, - 104,111,111,107,32,102,111,114,32,105,109,112,111,114,116,108, - 105,98,46,109,97,99,104,105,110,101,114,121,46,70,105,108, - 101,70,105,110,100,101,114,46,122,30,111,110,108,121,32,100, - 105,114,101,99,116,111,114,105,101,115,32,97,114,101,32,115, - 117,112,112,111,114,116,101,100,41,1,114,35,0,0,0,41, - 2,114,46,0,0,0,114,101,0,0,0,41,1,114,35,0, - 0,0,41,2,114,172,0,0,0,114,17,1,0,0,114,2, - 0,0,0,114,4,0,0,0,218,24,112,97,116,104,95,104, - 111,111,107,95,102,111,114,95,70,105,108,101,70,105,110,100, - 101,114,131,5,0,0,115,6,0,0,0,0,2,8,1,12, - 1,122,54,70,105,108,101,70,105,110,100,101,114,46,112,97, - 116,104,95,104,111,111,107,46,60,108,111,99,97,108,115,62, - 46,112,97,116,104,95,104,111,111,107,95,102,111,114,95,70, - 105,108,101,70,105,110,100,101,114,114,2,0,0,0,41,3, - 114,172,0,0,0,114,17,1,0,0,114,23,1,0,0,114, - 2,0,0,0,41,2,114,172,0,0,0,114,17,1,0,0, - 114,4,0,0,0,218,9,112,97,116,104,95,104,111,111,107, - 121,5,0,0,115,4,0,0,0,0,10,14,6,122,20,70, - 105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104, - 111,111,107,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,12,0,0,0,100,1,160, - 0,124,0,106,1,161,1,83,0,41,2,78,122,16,70,105, - 108,101,70,105,110,100,101,114,40,123,33,114,125,41,41,2, - 114,48,0,0,0,114,35,0,0,0,41,1,114,102,0,0, + 0,218,16,95,108,101,103,97,99,121,95,103,101,116,95,115, + 112,101,99,167,4,0,0,115,18,0,0,0,0,4,10,1, + 16,2,10,1,4,1,8,1,12,1,12,1,6,1,122,27, + 80,97,116,104,70,105,110,100,101,114,46,95,108,101,103,97, + 99,121,95,103,101,116,95,115,112,101,99,78,99,4,0,0, + 0,0,0,0,0,9,0,0,0,5,0,0,0,67,0,0, + 0,115,170,0,0,0,103,0,125,4,120,160,124,2,68,0, + 93,130,125,5,116,0,124,5,116,1,116,2,102,2,131,2, + 115,30,113,10,124,0,160,3,124,5,161,1,125,6,124,6, + 100,1,107,9,114,10,116,4,124,6,100,2,131,2,114,72, + 124,6,160,5,124,1,124,3,161,2,125,7,110,12,124,0, + 160,6,124,1,124,6,161,2,125,7,124,7,100,1,107,8, + 114,94,113,10,124,7,106,7,100,1,107,9,114,108,124,7, + 83,0,124,7,106,8,125,8,124,8,100,1,107,8,114,130, + 116,9,100,3,131,1,130,1,124,4,160,10,124,8,161,1, + 1,0,113,10,87,0,116,11,160,12,124,1,100,1,161,2, + 125,7,124,4,124,7,95,8,124,7,83,0,100,1,83,0, + 41,4,122,63,70,105,110,100,32,116,104,101,32,108,111,97, + 100,101,114,32,111,114,32,110,97,109,101,115,112,97,99,101, + 95,112,97,116,104,32,102,111,114,32,116,104,105,115,32,109, + 111,100,117,108,101,47,112,97,99,107,97,103,101,32,110,97, + 109,101,46,78,114,182,0,0,0,122,19,115,112,101,99,32, + 109,105,115,115,105,110,103,32,108,111,97,100,101,114,41,13, + 114,141,0,0,0,114,71,0,0,0,218,5,98,121,116,101, + 115,114,6,1,0,0,114,110,0,0,0,114,182,0,0,0, + 114,7,1,0,0,114,122,0,0,0,114,158,0,0,0,114, + 101,0,0,0,114,147,0,0,0,114,116,0,0,0,114,162, + 0,0,0,41,9,114,172,0,0,0,114,121,0,0,0,114, + 35,0,0,0,114,181,0,0,0,218,14,110,97,109,101,115, + 112,97,99,101,95,112,97,116,104,90,5,101,110,116,114,121, + 114,1,1,0,0,114,166,0,0,0,114,123,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,9, + 95,103,101,116,95,115,112,101,99,182,4,0,0,115,40,0, + 0,0,0,5,4,1,10,1,14,1,2,1,10,1,8,1, + 10,1,14,2,12,1,8,1,2,1,10,1,4,1,6,1, + 8,1,8,5,14,2,12,1,6,1,122,20,80,97,116,104, + 70,105,110,100,101,114,46,95,103,101,116,95,115,112,101,99, + 99,4,0,0,0,0,0,0,0,6,0,0,0,5,0,0, + 0,67,0,0,0,115,100,0,0,0,124,2,100,1,107,8, + 114,14,116,0,106,1,125,2,124,0,160,2,124,1,124,2, + 124,3,161,3,125,4,124,4,100,1,107,8,114,40,100,1, + 83,0,124,4,106,3,100,1,107,8,114,92,124,4,106,4, + 125,5,124,5,114,86,100,2,124,4,95,5,116,6,124,1, + 124,5,124,0,106,2,131,3,124,4,95,4,124,4,83,0, + 100,1,83,0,110,4,124,4,83,0,100,1,83,0,41,3, + 122,141,84,114,121,32,116,111,32,102,105,110,100,32,97,32, + 115,112,101,99,32,102,111,114,32,39,102,117,108,108,110,97, + 109,101,39,32,111,110,32,115,121,115,46,112,97,116,104,32, + 111,114,32,39,112,97,116,104,39,46,10,10,32,32,32,32, + 32,32,32,32,84,104,101,32,115,101,97,114,99,104,32,105, + 115,32,98,97,115,101,100,32,111,110,32,115,121,115,46,112, + 97,116,104,95,104,111,111,107,115,32,97,110,100,32,115,121, + 115,46,112,97,116,104,95,105,109,112,111,114,116,101,114,95, + 99,97,99,104,101,46,10,32,32,32,32,32,32,32,32,78, + 90,9,110,97,109,101,115,112,97,99,101,41,7,114,6,0, + 0,0,114,35,0,0,0,114,10,1,0,0,114,122,0,0, + 0,114,158,0,0,0,114,160,0,0,0,114,232,0,0,0, + 41,6,114,172,0,0,0,114,121,0,0,0,114,35,0,0, + 0,114,181,0,0,0,114,166,0,0,0,114,9,1,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 182,0,0,0,214,4,0,0,115,26,0,0,0,0,6,8, + 1,6,1,14,1,8,1,4,1,10,1,6,1,4,3,6, + 1,16,1,4,2,6,2,122,20,80,97,116,104,70,105,110, + 100,101,114,46,102,105,110,100,95,115,112,101,99,99,3,0, + 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, + 0,0,115,30,0,0,0,124,0,160,0,124,1,124,2,161, + 2,125,3,124,3,100,1,107,8,114,24,100,1,83,0,124, + 3,106,1,83,0,41,2,122,170,102,105,110,100,32,116,104, + 101,32,109,111,100,117,108,101,32,111,110,32,115,121,115,46, + 112,97,116,104,32,111,114,32,39,112,97,116,104,39,32,98, + 97,115,101,100,32,111,110,32,115,121,115,46,112,97,116,104, + 95,104,111,111,107,115,32,97,110,100,10,32,32,32,32,32, + 32,32,32,115,121,115,46,112,97,116,104,95,105,109,112,111, + 114,116,101,114,95,99,97,99,104,101,46,10,10,32,32,32, + 32,32,32,32,32,84,104,105,115,32,109,101,116,104,111,100, + 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, + 32,85,115,101,32,102,105,110,100,95,115,112,101,99,40,41, + 32,105,110,115,116,101,97,100,46,10,10,32,32,32,32,32, + 32,32,32,78,41,2,114,182,0,0,0,114,122,0,0,0, + 41,4,114,172,0,0,0,114,121,0,0,0,114,35,0,0, + 0,114,166,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,183,0,0,0,238,4,0,0,115,8, + 0,0,0,0,8,12,1,8,1,4,1,122,22,80,97,116, + 104,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, + 117,108,101,41,1,78,41,2,78,78,41,1,78,41,12,114, + 107,0,0,0,114,106,0,0,0,114,108,0,0,0,114,109, + 0,0,0,114,184,0,0,0,114,254,0,0,0,114,3,1, + 0,0,114,6,1,0,0,114,7,1,0,0,114,10,1,0, + 0,114,182,0,0,0,114,183,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 253,0,0,0,120,4,0,0,115,20,0,0,0,12,4,12, + 8,12,13,12,22,12,15,2,1,12,31,2,1,12,23,2, + 1,114,253,0,0,0,99,0,0,0,0,0,0,0,0,0, + 0,0,0,3,0,0,0,64,0,0,0,115,90,0,0,0, + 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, + 132,0,90,4,100,4,100,5,132,0,90,5,101,6,90,7, + 100,6,100,7,132,0,90,8,100,8,100,9,132,0,90,9, + 100,19,100,11,100,12,132,1,90,10,100,13,100,14,132,0, + 90,11,101,12,100,15,100,16,132,0,131,1,90,13,100,17, + 100,18,132,0,90,14,100,10,83,0,41,20,218,10,70,105, + 108,101,70,105,110,100,101,114,122,172,70,105,108,101,45,98, + 97,115,101,100,32,102,105,110,100,101,114,46,10,10,32,32, + 32,32,73,110,116,101,114,97,99,116,105,111,110,115,32,119, + 105,116,104,32,116,104,101,32,102,105,108,101,32,115,121,115, + 116,101,109,32,97,114,101,32,99,97,99,104,101,100,32,102, + 111,114,32,112,101,114,102,111,114,109,97,110,99,101,44,32, + 98,101,105,110,103,10,32,32,32,32,114,101,102,114,101,115, + 104,101,100,32,119,104,101,110,32,116,104,101,32,100,105,114, + 101,99,116,111,114,121,32,116,104,101,32,102,105,110,100,101, + 114,32,105,115,32,104,97,110,100,108,105,110,103,32,104,97, + 115,32,98,101,101,110,32,109,111,100,105,102,105,101,100,46, + 10,10,32,32,32,32,99,2,0,0,0,0,0,0,0,5, + 0,0,0,6,0,0,0,7,0,0,0,115,88,0,0,0, + 103,0,125,3,120,40,124,2,68,0,93,32,92,2,137,0, + 125,4,124,3,160,0,135,0,102,1,100,1,100,2,132,8, + 124,4,68,0,131,1,161,1,1,0,113,10,87,0,124,3, + 124,0,95,1,124,1,112,58,100,3,124,0,95,2,100,4, + 124,0,95,3,116,4,131,0,124,0,95,5,116,4,131,0, + 124,0,95,6,100,5,83,0,41,6,122,154,73,110,105,116, + 105,97,108,105,122,101,32,119,105,116,104,32,116,104,101,32, + 112,97,116,104,32,116,111,32,115,101,97,114,99,104,32,111, + 110,32,97,110,100,32,97,32,118,97,114,105,97,98,108,101, + 32,110,117,109,98,101,114,32,111,102,10,32,32,32,32,32, + 32,32,32,50,45,116,117,112,108,101,115,32,99,111,110,116, + 97,105,110,105,110,103,32,116,104,101,32,108,111,97,100,101, + 114,32,97,110,100,32,116,104,101,32,102,105,108,101,32,115, + 117,102,102,105,120,101,115,32,116,104,101,32,108,111,97,100, + 101,114,10,32,32,32,32,32,32,32,32,114,101,99,111,103, + 110,105,122,101,115,46,99,1,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,51,0,0,0,115,22,0,0,0, + 124,0,93,14,125,1,124,1,136,0,102,2,86,0,1,0, + 113,2,100,0,83,0,41,1,78,114,2,0,0,0,41,2, + 114,22,0,0,0,114,227,0,0,0,41,1,114,122,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,229,0,0,0, + 11,5,0,0,115,2,0,0,0,4,0,122,38,70,105,108, + 101,70,105,110,100,101,114,46,95,95,105,110,105,116,95,95, + 46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,120, + 112,114,62,114,59,0,0,0,114,89,0,0,0,78,41,7, + 114,147,0,0,0,218,8,95,108,111,97,100,101,114,115,114, + 35,0,0,0,218,11,95,112,97,116,104,95,109,116,105,109, + 101,218,3,115,101,116,218,11,95,112,97,116,104,95,99,97, + 99,104,101,218,19,95,114,101,108,97,120,101,100,95,112,97, + 116,104,95,99,97,99,104,101,41,5,114,102,0,0,0,114, + 35,0,0,0,218,14,108,111,97,100,101,114,95,100,101,116, + 97,105,108,115,90,7,108,111,97,100,101,114,115,114,168,0, + 0,0,114,2,0,0,0,41,1,114,122,0,0,0,114,4, + 0,0,0,114,186,0,0,0,5,5,0,0,115,16,0,0, + 0,0,4,4,1,14,1,28,1,6,2,10,1,6,1,8, + 1,122,19,70,105,108,101,70,105,110,100,101,114,46,95,95, + 105,110,105,116,95,95,99,1,0,0,0,0,0,0,0,1, + 0,0,0,2,0,0,0,67,0,0,0,115,10,0,0,0, + 100,1,124,0,95,0,100,2,83,0,41,3,122,31,73,110, + 118,97,108,105,100,97,116,101,32,116,104,101,32,100,105,114, + 101,99,116,111,114,121,32,109,116,105,109,101,46,114,89,0, + 0,0,78,41,1,114,13,1,0,0,41,1,114,102,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,248,0,0,0,139,5,0,0,115,2,0,0,0,0,1, - 122,19,70,105,108,101,70,105,110,100,101,114,46,95,95,114, - 101,112,114,95,95,41,1,78,41,15,114,107,0,0,0,114, - 106,0,0,0,114,108,0,0,0,114,109,0,0,0,114,186, - 0,0,0,114,254,0,0,0,114,125,0,0,0,114,183,0, - 0,0,114,119,0,0,0,114,10,1,0,0,114,182,0,0, - 0,114,18,1,0,0,114,184,0,0,0,114,24,1,0,0, - 114,248,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,11,1,0,0,252,4, - 0,0,115,18,0,0,0,12,9,8,14,8,4,4,2,8, - 12,8,5,10,48,8,31,12,18,114,11,1,0,0,99,4, - 0,0,0,0,0,0,0,6,0,0,0,11,0,0,0,67, - 0,0,0,115,146,0,0,0,124,0,160,0,100,1,161,1, - 125,4,124,0,160,0,100,2,161,1,125,5,124,4,115,66, - 124,5,114,36,124,5,106,1,125,4,110,30,124,2,124,3, - 107,2,114,56,116,2,124,1,124,2,131,2,125,4,110,10, - 116,3,124,1,124,2,131,2,125,4,124,5,115,84,116,4, - 124,1,124,2,124,4,100,3,141,3,125,5,121,36,124,5, - 124,0,100,2,60,0,124,4,124,0,100,1,60,0,124,2, - 124,0,100,4,60,0,124,3,124,0,100,5,60,0,87,0, - 110,20,4,0,116,5,107,10,114,140,1,0,1,0,1,0, - 89,0,110,2,88,0,100,0,83,0,41,6,78,218,10,95, - 95,108,111,97,100,101,114,95,95,218,8,95,95,115,112,101, - 99,95,95,41,1,114,122,0,0,0,90,8,95,95,102,105, - 108,101,95,95,90,10,95,95,99,97,99,104,101,100,95,95, - 41,6,218,3,103,101,116,114,122,0,0,0,114,225,0,0, - 0,114,220,0,0,0,114,169,0,0,0,218,9,69,120,99, - 101,112,116,105,111,110,41,6,90,2,110,115,114,100,0,0, - 0,90,8,112,97,116,104,110,97,109,101,90,9,99,112,97, - 116,104,110,97,109,101,114,122,0,0,0,114,166,0,0,0, + 114,254,0,0,0,19,5,0,0,115,2,0,0,0,0,2, + 122,28,70,105,108,101,70,105,110,100,101,114,46,105,110,118, + 97,108,105,100,97,116,101,95,99,97,99,104,101,115,99,2, + 0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,67, + 0,0,0,115,42,0,0,0,124,0,160,0,124,1,161,1, + 125,2,124,2,100,1,107,8,114,26,100,1,103,0,102,2, + 83,0,124,2,106,1,124,2,106,2,112,38,103,0,102,2, + 83,0,41,2,122,197,84,114,121,32,116,111,32,102,105,110, + 100,32,97,32,108,111,97,100,101,114,32,102,111,114,32,116, + 104,101,32,115,112,101,99,105,102,105,101,100,32,109,111,100, + 117,108,101,44,32,111,114,32,116,104,101,32,110,97,109,101, + 115,112,97,99,101,10,32,32,32,32,32,32,32,32,112,97, + 99,107,97,103,101,32,112,111,114,116,105,111,110,115,46,32, + 82,101,116,117,114,110,115,32,40,108,111,97,100,101,114,44, + 32,108,105,115,116,45,111,102,45,112,111,114,116,105,111,110, + 115,41,46,10,10,32,32,32,32,32,32,32,32,84,104,105, + 115,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,46,32,32,85,115,101,32,102,105,110, + 100,95,115,112,101,99,40,41,32,105,110,115,116,101,97,100, + 46,10,10,32,32,32,32,32,32,32,32,78,41,3,114,182, + 0,0,0,114,122,0,0,0,114,158,0,0,0,41,3,114, + 102,0,0,0,114,121,0,0,0,114,166,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,119,0, + 0,0,25,5,0,0,115,8,0,0,0,0,7,10,1,8, + 1,8,1,122,22,70,105,108,101,70,105,110,100,101,114,46, + 102,105,110,100,95,108,111,97,100,101,114,99,6,0,0,0, + 0,0,0,0,7,0,0,0,6,0,0,0,67,0,0,0, + 115,26,0,0,0,124,1,124,2,124,3,131,2,125,6,116, + 0,124,2,124,3,124,6,124,4,100,1,141,4,83,0,41, + 2,78,41,2,114,122,0,0,0,114,158,0,0,0,41,1, + 114,169,0,0,0,41,7,114,102,0,0,0,114,167,0,0, + 0,114,121,0,0,0,114,35,0,0,0,90,4,115,109,115, + 108,114,181,0,0,0,114,122,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,10,1,0,0,37, + 5,0,0,115,6,0,0,0,0,1,10,1,8,1,122,20, + 70,105,108,101,70,105,110,100,101,114,46,95,103,101,116,95, + 115,112,101,99,78,99,3,0,0,0,0,0,0,0,14,0, + 0,0,16,0,0,0,67,0,0,0,115,98,1,0,0,100, + 1,125,3,124,1,160,0,100,2,161,1,100,3,25,0,125, + 4,121,24,116,1,124,0,106,2,112,34,116,3,160,4,161, + 0,131,1,106,5,125,5,87,0,110,24,4,0,116,6,107, + 10,114,66,1,0,1,0,1,0,100,4,125,5,89,0,110, + 2,88,0,124,5,124,0,106,7,107,3,114,92,124,0,160, + 8,161,0,1,0,124,5,124,0,95,7,116,9,131,0,114, + 114,124,0,106,10,125,6,124,4,160,11,161,0,125,7,110, + 10,124,0,106,12,125,6,124,4,125,7,124,7,124,6,107, + 6,114,218,116,13,124,0,106,2,124,4,131,2,125,8,120, + 72,124,0,106,14,68,0,93,54,92,2,125,9,125,10,100, + 5,124,9,23,0,125,11,116,13,124,8,124,11,131,2,125, + 12,116,15,124,12,131,1,114,152,124,0,160,16,124,10,124, + 1,124,12,124,8,103,1,124,2,161,5,83,0,113,152,87, + 0,116,17,124,8,131,1,125,3,120,88,124,0,106,14,68, + 0,93,78,92,2,125,9,125,10,116,13,124,0,106,2,124, + 4,124,9,23,0,131,2,125,12,116,18,106,19,100,6,124, + 12,100,3,100,7,141,3,1,0,124,7,124,9,23,0,124, + 6,107,6,114,226,116,15,124,12,131,1,114,226,124,0,160, + 16,124,10,124,1,124,12,100,8,124,2,161,5,83,0,113, + 226,87,0,124,3,144,1,114,94,116,18,160,19,100,9,124, + 8,161,2,1,0,116,18,160,20,124,1,100,8,161,2,125, + 13,124,8,103,1,124,13,95,21,124,13,83,0,100,8,83, + 0,41,10,122,111,84,114,121,32,116,111,32,102,105,110,100, + 32,97,32,115,112,101,99,32,102,111,114,32,116,104,101,32, + 115,112,101,99,105,102,105,101,100,32,109,111,100,117,108,101, + 46,10,10,32,32,32,32,32,32,32,32,82,101,116,117,114, + 110,115,32,116,104,101,32,109,97,116,99,104,105,110,103,32, + 115,112,101,99,44,32,111,114,32,78,111,110,101,32,105,102, + 32,110,111,116,32,102,111,117,110,100,46,10,32,32,32,32, + 32,32,32,32,70,114,59,0,0,0,114,57,0,0,0,114, + 89,0,0,0,114,186,0,0,0,122,9,116,114,121,105,110, + 103,32,123,125,41,1,90,9,118,101,114,98,111,115,105,116, + 121,78,122,25,112,111,115,115,105,98,108,101,32,110,97,109, + 101,115,112,97,99,101,32,102,111,114,32,123,125,41,22,114, + 32,0,0,0,114,39,0,0,0,114,35,0,0,0,114,1, + 0,0,0,114,45,0,0,0,114,221,0,0,0,114,40,0, + 0,0,114,13,1,0,0,218,11,95,102,105,108,108,95,99, + 97,99,104,101,114,5,0,0,0,114,16,1,0,0,114,90, + 0,0,0,114,15,1,0,0,114,28,0,0,0,114,12,1, + 0,0,114,44,0,0,0,114,10,1,0,0,114,46,0,0, + 0,114,116,0,0,0,114,130,0,0,0,114,162,0,0,0, + 114,158,0,0,0,41,14,114,102,0,0,0,114,121,0,0, + 0,114,181,0,0,0,90,12,105,115,95,110,97,109,101,115, + 112,97,99,101,90,11,116,97,105,108,95,109,111,100,117,108, + 101,114,149,0,0,0,90,5,99,97,99,104,101,90,12,99, + 97,99,104,101,95,109,111,100,117,108,101,90,9,98,97,115, + 101,95,112,97,116,104,114,227,0,0,0,114,167,0,0,0, + 90,13,105,110,105,116,95,102,105,108,101,110,97,109,101,90, + 9,102,117,108,108,95,112,97,116,104,114,166,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,182, + 0,0,0,42,5,0,0,115,70,0,0,0,0,5,4,1, + 14,1,2,1,24,1,14,1,10,1,10,1,8,1,6,2, + 6,1,6,1,10,2,6,1,4,2,8,1,12,1,16,1, + 8,1,10,1,8,1,24,4,8,2,16,1,16,1,16,1, + 12,1,8,1,10,1,12,1,6,1,12,1,12,1,8,1, + 4,1,122,20,70,105,108,101,70,105,110,100,101,114,46,102, + 105,110,100,95,115,112,101,99,99,1,0,0,0,0,0,0, + 0,9,0,0,0,14,0,0,0,67,0,0,0,115,194,0, + 0,0,124,0,106,0,125,1,121,22,116,1,160,2,124,1, + 112,22,116,1,160,3,161,0,161,1,125,2,87,0,110,30, + 4,0,116,4,116,5,116,6,102,3,107,10,114,58,1,0, + 1,0,1,0,103,0,125,2,89,0,110,2,88,0,116,7, + 106,8,160,9,100,1,161,1,115,84,116,10,124,2,131,1, + 124,0,95,11,110,78,116,10,131,0,125,3,120,64,124,2, + 68,0,93,56,125,4,124,4,160,12,100,2,161,1,92,3, + 125,5,125,6,125,7,124,6,114,138,100,3,160,13,124,5, + 124,7,160,14,161,0,161,2,125,8,110,4,124,5,125,8, + 124,3,160,15,124,8,161,1,1,0,113,96,87,0,124,3, + 124,0,95,11,116,7,106,8,160,9,116,16,161,1,114,190, + 100,4,100,5,132,0,124,2,68,0,131,1,124,0,95,17, + 100,6,83,0,41,7,122,68,70,105,108,108,32,116,104,101, + 32,99,97,99,104,101,32,111,102,32,112,111,116,101,110,116, + 105,97,108,32,109,111,100,117,108,101,115,32,97,110,100,32, + 112,97,99,107,97,103,101,115,32,102,111,114,32,116,104,105, + 115,32,100,105,114,101,99,116,111,114,121,46,114,0,0,0, + 0,114,59,0,0,0,122,5,123,125,46,123,125,99,1,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,83,0, + 0,0,115,20,0,0,0,104,0,124,0,93,12,125,1,124, + 1,160,0,161,0,146,2,113,4,83,0,114,2,0,0,0, + 41,1,114,90,0,0,0,41,2,114,22,0,0,0,90,2, + 102,110,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,250,9,60,115,101,116,99,111,109,112,62,119,5,0,0, + 115,2,0,0,0,6,0,122,41,70,105,108,101,70,105,110, + 100,101,114,46,95,102,105,108,108,95,99,97,99,104,101,46, + 60,108,111,99,97,108,115,62,46,60,115,101,116,99,111,109, + 112,62,78,41,18,114,35,0,0,0,114,1,0,0,0,90, + 7,108,105,115,116,100,105,114,114,45,0,0,0,114,4,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,6,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,14,1,0,0,114,15,1,0,0, + 114,85,0,0,0,114,48,0,0,0,114,90,0,0,0,218, + 3,97,100,100,114,9,0,0,0,114,16,1,0,0,41,9, + 114,102,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,249,0,0,0, + 114,100,0,0,0,114,239,0,0,0,114,227,0,0,0,90, + 8,110,101,119,95,110,97,109,101,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,18,1,0,0,90,5,0, + 0,115,34,0,0,0,0,2,6,1,2,1,22,1,20,3, + 10,3,12,1,12,7,6,1,10,1,16,1,4,1,18,2, + 4,1,14,1,6,1,12,1,122,22,70,105,108,101,70,105, + 110,100,101,114,46,95,102,105,108,108,95,99,97,99,104,101, + 99,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0, + 0,7,0,0,0,115,18,0,0,0,135,0,135,1,102,2, + 100,1,100,2,132,8,125,2,124,2,83,0,41,3,97,20, + 1,0,0,65,32,99,108,97,115,115,32,109,101,116,104,111, + 100,32,119,104,105,99,104,32,114,101,116,117,114,110,115,32, + 97,32,99,108,111,115,117,114,101,32,116,111,32,117,115,101, + 32,111,110,32,115,121,115,46,112,97,116,104,95,104,111,111, + 107,10,32,32,32,32,32,32,32,32,119,104,105,99,104,32, + 119,105,108,108,32,114,101,116,117,114,110,32,97,110,32,105, + 110,115,116,97,110,99,101,32,117,115,105,110,103,32,116,104, + 101,32,115,112,101,99,105,102,105,101,100,32,108,111,97,100, + 101,114,115,32,97,110,100,32,116,104,101,32,112,97,116,104, + 10,32,32,32,32,32,32,32,32,99,97,108,108,101,100,32, + 111,110,32,116,104,101,32,99,108,111,115,117,114,101,46,10, + 10,32,32,32,32,32,32,32,32,73,102,32,116,104,101,32, + 112,97,116,104,32,99,97,108,108,101,100,32,111,110,32,116, + 104,101,32,99,108,111,115,117,114,101,32,105,115,32,110,111, + 116,32,97,32,100,105,114,101,99,116,111,114,121,44,32,73, + 109,112,111,114,116,69,114,114,111,114,32,105,115,10,32,32, + 32,32,32,32,32,32,114,97,105,115,101,100,46,10,10,32, + 32,32,32,32,32,32,32,99,1,0,0,0,0,0,0,0, + 1,0,0,0,4,0,0,0,19,0,0,0,115,34,0,0, + 0,116,0,124,0,131,1,115,20,116,1,100,1,124,0,100, + 2,141,2,130,1,136,0,124,0,102,1,136,1,158,2,142, + 0,83,0,41,3,122,45,80,97,116,104,32,104,111,111,107, + 32,102,111,114,32,105,109,112,111,114,116,108,105,98,46,109, + 97,99,104,105,110,101,114,121,46,70,105,108,101,70,105,110, + 100,101,114,46,122,30,111,110,108,121,32,100,105,114,101,99, + 116,111,114,105,101,115,32,97,114,101,32,115,117,112,112,111, + 114,116,101,100,41,1,114,35,0,0,0,41,2,114,46,0, + 0,0,114,101,0,0,0,41,1,114,35,0,0,0,41,2, + 114,172,0,0,0,114,17,1,0,0,114,2,0,0,0,114, + 4,0,0,0,218,24,112,97,116,104,95,104,111,111,107,95, + 102,111,114,95,70,105,108,101,70,105,110,100,101,114,131,5, + 0,0,115,6,0,0,0,0,2,8,1,12,1,122,54,70, + 105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104, + 111,111,107,46,60,108,111,99,97,108,115,62,46,112,97,116, + 104,95,104,111,111,107,95,102,111,114,95,70,105,108,101,70, + 105,110,100,101,114,114,2,0,0,0,41,3,114,172,0,0, + 0,114,17,1,0,0,114,23,1,0,0,114,2,0,0,0, + 41,2,114,172,0,0,0,114,17,1,0,0,114,4,0,0, + 0,218,9,112,97,116,104,95,104,111,111,107,121,5,0,0, + 115,4,0,0,0,0,10,14,6,122,20,70,105,108,101,70, + 105,110,100,101,114,46,112,97,116,104,95,104,111,111,107,99, + 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,115,12,0,0,0,100,1,160,0,124,0,106, + 1,161,1,83,0,41,2,78,122,16,70,105,108,101,70,105, + 110,100,101,114,40,123,33,114,125,41,41,2,114,48,0,0, + 0,114,35,0,0,0,41,1,114,102,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,248,0,0, + 0,139,5,0,0,115,2,0,0,0,0,1,122,19,70,105, + 108,101,70,105,110,100,101,114,46,95,95,114,101,112,114,95, + 95,41,1,78,41,15,114,107,0,0,0,114,106,0,0,0, + 114,108,0,0,0,114,109,0,0,0,114,186,0,0,0,114, + 254,0,0,0,114,125,0,0,0,114,183,0,0,0,114,119, + 0,0,0,114,10,1,0,0,114,182,0,0,0,114,18,1, + 0,0,114,184,0,0,0,114,24,1,0,0,114,248,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,11,1,0,0,252,4,0,0,115,18, + 0,0,0,12,9,8,14,8,4,4,2,8,12,8,5,10, + 48,8,31,12,18,114,11,1,0,0,99,4,0,0,0,0, + 0,0,0,6,0,0,0,11,0,0,0,67,0,0,0,115, + 146,0,0,0,124,0,160,0,100,1,161,1,125,4,124,0, + 160,0,100,2,161,1,125,5,124,4,115,66,124,5,114,36, + 124,5,106,1,125,4,110,30,124,2,124,3,107,2,114,56, + 116,2,124,1,124,2,131,2,125,4,110,10,116,3,124,1, + 124,2,131,2,125,4,124,5,115,84,116,4,124,1,124,2, + 124,4,100,3,141,3,125,5,121,36,124,5,124,0,100,2, + 60,0,124,4,124,0,100,1,60,0,124,2,124,0,100,4, + 60,0,124,3,124,0,100,5,60,0,87,0,110,20,4,0, + 116,5,107,10,114,140,1,0,1,0,1,0,89,0,110,2, + 88,0,100,0,83,0,41,6,78,218,10,95,95,108,111,97, + 100,101,114,95,95,218,8,95,95,115,112,101,99,95,95,41, + 1,114,122,0,0,0,90,8,95,95,102,105,108,101,95,95, + 90,10,95,95,99,97,99,104,101,100,95,95,41,6,218,3, + 103,101,116,114,122,0,0,0,114,225,0,0,0,114,220,0, + 0,0,114,169,0,0,0,218,9,69,120,99,101,112,116,105, + 111,110,41,6,90,2,110,115,114,100,0,0,0,90,8,112, + 97,116,104,110,97,109,101,90,9,99,112,97,116,104,110,97, + 109,101,114,122,0,0,0,114,166,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,14,95,102,105, + 120,95,117,112,95,109,111,100,117,108,101,145,5,0,0,115, + 34,0,0,0,0,2,10,1,10,1,4,1,4,1,8,1, + 8,1,12,2,10,1,4,1,14,1,2,1,8,1,8,1, + 8,1,12,1,14,2,114,29,1,0,0,99,0,0,0,0, + 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, + 115,38,0,0,0,116,0,116,1,160,2,161,0,102,2,125, + 0,116,3,116,4,102,2,125,1,116,5,116,6,102,2,125, + 2,124,0,124,1,124,2,103,3,83,0,41,1,122,95,82, + 101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102, + 32,102,105,108,101,45,98,97,115,101,100,32,109,111,100,117, + 108,101,32,108,111,97,100,101,114,115,46,10,10,32,32,32, + 32,69,97,99,104,32,105,116,101,109,32,105,115,32,97,32, + 116,117,112,108,101,32,40,108,111,97,100,101,114,44,32,115, + 117,102,102,105,120,101,115,41,46,10,32,32,32,32,41,7, + 114,226,0,0,0,114,143,0,0,0,218,18,101,120,116,101, + 110,115,105,111,110,95,115,117,102,102,105,120,101,115,114,220, + 0,0,0,114,86,0,0,0,114,225,0,0,0,114,76,0, + 0,0,41,3,90,10,101,120,116,101,110,115,105,111,110,115, + 90,6,115,111,117,114,99,101,90,8,98,121,116,101,99,111, + 100,101,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,163,0,0,0,168,5,0,0,115,8,0,0,0,0, + 5,12,1,8,1,8,1,114,163,0,0,0,99,1,0,0, + 0,0,0,0,0,12,0,0,0,12,0,0,0,67,0,0, + 0,115,156,1,0,0,124,0,97,0,116,0,106,1,97,1, + 116,0,106,2,97,2,116,1,106,3,116,4,25,0,125,1, + 120,56,100,1,68,0,93,48,125,2,124,2,116,1,106,3, + 107,7,114,58,116,0,160,5,124,2,161,1,125,3,110,10, + 116,1,106,3,124,2,25,0,125,3,116,6,124,1,124,2, + 124,3,131,3,1,0,113,32,87,0,100,2,100,3,103,1, + 102,2,100,4,100,5,100,3,103,2,102,2,102,2,125,4, + 120,118,124,4,68,0,93,102,92,2,125,5,125,6,116,7, + 100,6,100,7,132,0,124,6,68,0,131,1,131,1,115,142, + 116,8,130,1,124,6,100,8,25,0,125,7,124,5,116,1, + 106,3,107,6,114,174,116,1,106,3,124,5,25,0,125,8, + 80,0,113,112,121,16,116,0,160,5,124,5,161,1,125,8, + 80,0,87,0,113,112,4,0,116,9,107,10,114,212,1,0, + 1,0,1,0,119,112,89,0,113,112,88,0,113,112,87,0, + 116,9,100,9,131,1,130,1,116,6,124,1,100,10,124,8, + 131,3,1,0,116,6,124,1,100,11,124,7,131,3,1,0, + 116,6,124,1,100,12,100,13,160,10,124,6,161,1,131,3, + 1,0,116,0,160,5,100,14,161,1,125,9,116,6,124,1, + 100,14,124,9,131,3,1,0,116,0,160,5,100,15,161,1, + 125,10,116,6,124,1,100,15,124,10,131,3,1,0,124,5, + 100,4,107,2,144,1,114,88,116,0,160,5,100,16,161,1, + 125,11,116,6,124,1,100,17,124,11,131,3,1,0,116,6, + 124,1,100,18,116,11,131,0,131,3,1,0,116,12,160,13, + 116,2,160,14,161,0,161,1,1,0,124,5,100,4,107,2, + 144,1,114,152,116,15,160,16,100,19,161,1,1,0,100,20, + 116,12,107,6,144,1,114,152,100,21,116,17,95,18,100,22, + 83,0,41,23,122,205,83,101,116,117,112,32,116,104,101,32, + 112,97,116,104,45,98,97,115,101,100,32,105,109,112,111,114, + 116,101,114,115,32,102,111,114,32,105,109,112,111,114,116,108, + 105,98,32,98,121,32,105,109,112,111,114,116,105,110,103,32, + 110,101,101,100,101,100,10,32,32,32,32,98,117,105,108,116, + 45,105,110,32,109,111,100,117,108,101,115,32,97,110,100,32, + 105,110,106,101,99,116,105,110,103,32,116,104,101,109,32,105, + 110,116,111,32,116,104,101,32,103,108,111,98,97,108,32,110, + 97,109,101,115,112,97,99,101,46,10,10,32,32,32,32,79, + 116,104,101,114,32,99,111,109,112,111,110,101,110,116,115,32, + 97,114,101,32,101,120,116,114,97,99,116,101,100,32,102,114, + 111,109,32,116,104,101,32,99,111,114,101,32,98,111,111,116, + 115,116,114,97,112,32,109,111,100,117,108,101,46,10,10,32, + 32,32,32,41,4,114,50,0,0,0,114,61,0,0,0,218, + 8,98,117,105,108,116,105,110,115,114,140,0,0,0,90,5, + 112,111,115,105,120,250,1,47,90,2,110,116,250,1,92,99, + 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 115,0,0,0,115,26,0,0,0,124,0,93,18,125,1,116, + 0,124,1,131,1,100,0,107,2,86,0,1,0,113,2,100, + 1,83,0,41,2,114,29,0,0,0,78,41,1,114,31,0, + 0,0,41,2,114,22,0,0,0,114,79,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,229,0, + 0,0,204,5,0,0,115,2,0,0,0,4,0,122,25,95, + 115,101,116,117,112,46,60,108,111,99,97,108,115,62,46,60, + 103,101,110,101,120,112,114,62,114,60,0,0,0,122,30,105, + 109,112,111,114,116,108,105,98,32,114,101,113,117,105,114,101, + 115,32,112,111,115,105,120,32,111,114,32,110,116,114,1,0, + 0,0,114,25,0,0,0,114,21,0,0,0,114,30,0,0, + 0,90,7,95,116,104,114,101,97,100,90,8,95,119,101,97, + 107,114,101,102,90,6,119,105,110,114,101,103,114,171,0,0, + 0,114,5,0,0,0,122,4,46,112,121,119,122,6,95,100, + 46,112,121,100,84,78,41,19,114,116,0,0,0,114,6,0, + 0,0,114,143,0,0,0,114,241,0,0,0,114,107,0,0, + 0,90,18,95,98,117,105,108,116,105,110,95,102,114,111,109, + 95,110,97,109,101,114,111,0,0,0,218,3,97,108,108,114, + 151,0,0,0,114,101,0,0,0,114,26,0,0,0,114,11, + 0,0,0,114,231,0,0,0,114,147,0,0,0,114,30,1, + 0,0,114,86,0,0,0,114,165,0,0,0,114,170,0,0, + 0,114,174,0,0,0,41,12,218,17,95,98,111,111,116,115, + 116,114,97,112,95,109,111,100,117,108,101,90,11,115,101,108, + 102,95,109,111,100,117,108,101,90,12,98,117,105,108,116,105, + 110,95,110,97,109,101,90,14,98,117,105,108,116,105,110,95, + 109,111,100,117,108,101,90,10,111,115,95,100,101,116,97,105, + 108,115,90,10,98,117,105,108,116,105,110,95,111,115,114,21, + 0,0,0,114,25,0,0,0,90,9,111,115,95,109,111,100, + 117,108,101,90,13,116,104,114,101,97,100,95,109,111,100,117, + 108,101,90,14,119,101,97,107,114,101,102,95,109,111,100,117, + 108,101,90,13,119,105,110,114,101,103,95,109,111,100,117,108, + 101,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,6,95,115,101,116,117,112,179,5,0,0,115,76,0,0, + 0,0,8,4,1,6,1,6,3,10,1,10,1,10,1,12, + 2,10,1,16,3,22,1,14,2,22,1,8,1,10,1,10, + 1,4,2,2,1,10,1,6,1,14,1,12,2,8,1,12, + 1,12,1,18,3,10,1,12,3,10,1,12,3,10,1,10, + 1,12,3,14,1,14,1,10,1,10,1,10,1,114,36,1, + 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,4, + 0,0,0,67,0,0,0,115,50,0,0,0,116,0,124,0, + 131,1,1,0,116,1,131,0,125,1,116,2,106,3,160,4, + 116,5,106,6,124,1,142,0,103,1,161,1,1,0,116,2, + 106,7,160,8,116,9,161,1,1,0,100,1,83,0,41,2, + 122,41,73,110,115,116,97,108,108,32,116,104,101,32,112,97, + 116,104,45,98,97,115,101,100,32,105,109,112,111,114,116,32, + 99,111,109,112,111,110,101,110,116,115,46,78,41,10,114,36, + 1,0,0,114,163,0,0,0,114,6,0,0,0,114,2,1, + 0,0,114,147,0,0,0,114,11,1,0,0,114,24,1,0, + 0,218,9,109,101,116,97,95,112,97,116,104,114,165,0,0, + 0,114,253,0,0,0,41,2,114,35,1,0,0,90,17,115, + 117,112,112,111,114,116,101,100,95,108,111,97,100,101,114,115, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 14,95,102,105,120,95,117,112,95,109,111,100,117,108,101,145, - 5,0,0,115,34,0,0,0,0,2,10,1,10,1,4,1, - 4,1,8,1,8,1,12,2,10,1,4,1,14,1,2,1, - 8,1,8,1,8,1,12,1,14,2,114,29,1,0,0,99, - 0,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, - 67,0,0,0,115,38,0,0,0,116,0,116,1,160,2,161, - 0,102,2,125,0,116,3,116,4,102,2,125,1,116,5,116, - 6,102,2,125,2,124,0,124,1,124,2,103,3,83,0,41, - 1,122,95,82,101,116,117,114,110,115,32,97,32,108,105,115, - 116,32,111,102,32,102,105,108,101,45,98,97,115,101,100,32, - 109,111,100,117,108,101,32,108,111,97,100,101,114,115,46,10, - 10,32,32,32,32,69,97,99,104,32,105,116,101,109,32,105, - 115,32,97,32,116,117,112,108,101,32,40,108,111,97,100,101, - 114,44,32,115,117,102,102,105,120,101,115,41,46,10,32,32, - 32,32,41,7,114,226,0,0,0,114,143,0,0,0,218,18, - 101,120,116,101,110,115,105,111,110,95,115,117,102,102,105,120, - 101,115,114,220,0,0,0,114,86,0,0,0,114,225,0,0, - 0,114,76,0,0,0,41,3,90,10,101,120,116,101,110,115, - 105,111,110,115,90,6,115,111,117,114,99,101,90,8,98,121, - 116,101,99,111,100,101,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,163,0,0,0,168,5,0,0,115,8, - 0,0,0,0,5,12,1,8,1,8,1,114,163,0,0,0, - 99,1,0,0,0,0,0,0,0,12,0,0,0,12,0,0, - 0,67,0,0,0,115,156,1,0,0,124,0,97,0,116,0, - 106,1,97,1,116,0,106,2,97,2,116,1,106,3,116,4, - 25,0,125,1,120,56,100,1,68,0,93,48,125,2,124,2, - 116,1,106,3,107,7,114,58,116,0,160,5,124,2,161,1, - 125,3,110,10,116,1,106,3,124,2,25,0,125,3,116,6, - 124,1,124,2,124,3,131,3,1,0,113,32,87,0,100,2, - 100,3,103,1,102,2,100,4,100,5,100,3,103,2,102,2, - 102,2,125,4,120,118,124,4,68,0,93,102,92,2,125,5, - 125,6,116,7,100,6,100,7,132,0,124,6,68,0,131,1, - 131,1,115,142,116,8,130,1,124,6,100,8,25,0,125,7, - 124,5,116,1,106,3,107,6,114,174,116,1,106,3,124,5, - 25,0,125,8,80,0,113,112,121,16,116,0,160,5,124,5, - 161,1,125,8,80,0,87,0,113,112,4,0,116,9,107,10, - 114,212,1,0,1,0,1,0,119,112,89,0,113,112,88,0, - 113,112,87,0,116,9,100,9,131,1,130,1,116,6,124,1, - 100,10,124,8,131,3,1,0,116,6,124,1,100,11,124,7, - 131,3,1,0,116,6,124,1,100,12,100,13,160,10,124,6, - 161,1,131,3,1,0,116,0,160,5,100,14,161,1,125,9, - 116,6,124,1,100,14,124,9,131,3,1,0,116,0,160,5, - 100,15,161,1,125,10,116,6,124,1,100,15,124,10,131,3, - 1,0,124,5,100,4,107,2,144,1,114,88,116,0,160,5, - 100,16,161,1,125,11,116,6,124,1,100,17,124,11,131,3, - 1,0,116,6,124,1,100,18,116,11,131,0,131,3,1,0, - 116,12,160,13,116,2,160,14,161,0,161,1,1,0,124,5, - 100,4,107,2,144,1,114,152,116,15,160,16,100,19,161,1, - 1,0,100,20,116,12,107,6,144,1,114,152,100,21,116,17, - 95,18,100,22,83,0,41,23,122,205,83,101,116,117,112,32, - 116,104,101,32,112,97,116,104,45,98,97,115,101,100,32,105, - 109,112,111,114,116,101,114,115,32,102,111,114,32,105,109,112, - 111,114,116,108,105,98,32,98,121,32,105,109,112,111,114,116, - 105,110,103,32,110,101,101,100,101,100,10,32,32,32,32,98, - 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32, - 97,110,100,32,105,110,106,101,99,116,105,110,103,32,116,104, - 101,109,32,105,110,116,111,32,116,104,101,32,103,108,111,98, - 97,108,32,110,97,109,101,115,112,97,99,101,46,10,10,32, - 32,32,32,79,116,104,101,114,32,99,111,109,112,111,110,101, - 110,116,115,32,97,114,101,32,101,120,116,114,97,99,116,101, - 100,32,102,114,111,109,32,116,104,101,32,99,111,114,101,32, - 98,111,111,116,115,116,114,97,112,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,41,4,114,50,0,0,0,114,61, - 0,0,0,218,8,98,117,105,108,116,105,110,115,114,140,0, - 0,0,90,5,112,111,115,105,120,250,1,47,90,2,110,116, - 250,1,92,99,1,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,115,0,0,0,115,26,0,0,0,124,0,93, - 18,125,1,116,0,124,1,131,1,100,0,107,2,86,0,1, - 0,113,2,100,1,83,0,41,2,114,29,0,0,0,78,41, - 1,114,31,0,0,0,41,2,114,22,0,0,0,114,79,0, + 8,95,105,110,115,116,97,108,108,243,5,0,0,115,8,0, + 0,0,0,2,8,1,6,1,20,1,114,38,1,0,0,41, + 1,114,47,0,0,0,41,1,78,41,3,78,78,78,41,2, + 114,60,0,0,0,114,60,0,0,0,41,1,84,41,1,78, + 41,1,78,41,61,114,109,0,0,0,114,10,0,0,0,90, + 37,95,67,65,83,69,95,73,78,83,69,78,83,73,84,73, + 86,69,95,80,76,65,84,70,79,82,77,83,95,66,89,84, + 69,83,95,75,69,89,114,9,0,0,0,114,11,0,0,0, + 114,17,0,0,0,114,19,0,0,0,114,28,0,0,0,114, + 38,0,0,0,114,39,0,0,0,114,43,0,0,0,114,44, + 0,0,0,114,46,0,0,0,114,56,0,0,0,218,4,116, + 121,112,101,218,8,95,95,99,111,100,101,95,95,114,142,0, + 0,0,114,15,0,0,0,114,129,0,0,0,114,14,0,0, + 0,114,18,0,0,0,114,209,0,0,0,114,75,0,0,0, + 114,74,0,0,0,114,86,0,0,0,114,76,0,0,0,90, + 23,68,69,66,85,71,95,66,89,84,69,67,79,68,69,95, + 83,85,70,70,73,88,69,83,90,27,79,80,84,73,77,73, + 90,69,68,95,66,89,84,69,67,79,68,69,95,83,85,70, + 70,73,88,69,83,114,81,0,0,0,114,87,0,0,0,114, + 93,0,0,0,114,97,0,0,0,114,99,0,0,0,114,118, + 0,0,0,114,125,0,0,0,114,133,0,0,0,114,137,0, + 0,0,114,139,0,0,0,114,145,0,0,0,114,150,0,0, + 0,114,152,0,0,0,114,157,0,0,0,218,6,111,98,106, + 101,99,116,114,164,0,0,0,114,169,0,0,0,114,170,0, + 0,0,114,185,0,0,0,114,195,0,0,0,114,212,0,0, + 0,114,220,0,0,0,114,225,0,0,0,114,231,0,0,0, + 114,226,0,0,0,114,232,0,0,0,114,251,0,0,0,114, + 253,0,0,0,114,11,1,0,0,114,29,1,0,0,114,163, + 0,0,0,114,36,1,0,0,114,38,1,0,0,114,2,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,229,0,0,0,204,5,0,0,115,2,0,0,0,4, - 0,122,25,95,115,101,116,117,112,46,60,108,111,99,97,108, - 115,62,46,60,103,101,110,101,120,112,114,62,114,60,0,0, - 0,122,30,105,109,112,111,114,116,108,105,98,32,114,101,113, - 117,105,114,101,115,32,112,111,115,105,120,32,111,114,32,110, - 116,114,1,0,0,0,114,25,0,0,0,114,21,0,0,0, - 114,30,0,0,0,90,7,95,116,104,114,101,97,100,90,8, - 95,119,101,97,107,114,101,102,90,6,119,105,110,114,101,103, - 114,171,0,0,0,114,5,0,0,0,122,4,46,112,121,119, - 122,6,95,100,46,112,121,100,84,78,41,19,114,116,0,0, - 0,114,6,0,0,0,114,143,0,0,0,114,241,0,0,0, - 114,107,0,0,0,90,18,95,98,117,105,108,116,105,110,95, - 102,114,111,109,95,110,97,109,101,114,111,0,0,0,218,3, - 97,108,108,114,151,0,0,0,114,101,0,0,0,114,26,0, - 0,0,114,11,0,0,0,114,231,0,0,0,114,147,0,0, - 0,114,30,1,0,0,114,86,0,0,0,114,165,0,0,0, - 114,170,0,0,0,114,174,0,0,0,41,12,218,17,95,98, - 111,111,116,115,116,114,97,112,95,109,111,100,117,108,101,90, - 11,115,101,108,102,95,109,111,100,117,108,101,90,12,98,117, - 105,108,116,105,110,95,110,97,109,101,90,14,98,117,105,108, - 116,105,110,95,109,111,100,117,108,101,90,10,111,115,95,100, - 101,116,97,105,108,115,90,10,98,117,105,108,116,105,110,95, - 111,115,114,21,0,0,0,114,25,0,0,0,90,9,111,115, - 95,109,111,100,117,108,101,90,13,116,104,114,101,97,100,95, - 109,111,100,117,108,101,90,14,119,101,97,107,114,101,102,95, - 109,111,100,117,108,101,90,13,119,105,110,114,101,103,95,109, - 111,100,117,108,101,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,218,6,95,115,101,116,117,112,179,5,0,0, - 115,76,0,0,0,0,8,4,1,6,1,6,3,10,1,10, - 1,10,1,12,2,10,1,16,3,22,1,14,2,22,1,8, - 1,10,1,10,1,4,2,2,1,10,1,6,1,14,1,12, - 2,8,1,12,1,12,1,18,3,10,1,12,3,10,1,12, - 3,10,1,10,1,12,3,14,1,14,1,10,1,10,1,10, - 1,114,36,1,0,0,99,1,0,0,0,0,0,0,0,2, - 0,0,0,4,0,0,0,67,0,0,0,115,50,0,0,0, - 116,0,124,0,131,1,1,0,116,1,131,0,125,1,116,2, - 106,3,160,4,116,5,106,6,124,1,142,0,103,1,161,1, - 1,0,116,2,106,7,160,8,116,9,161,1,1,0,100,1, - 83,0,41,2,122,41,73,110,115,116,97,108,108,32,116,104, - 101,32,112,97,116,104,45,98,97,115,101,100,32,105,109,112, - 111,114,116,32,99,111,109,112,111,110,101,110,116,115,46,78, - 41,10,114,36,1,0,0,114,163,0,0,0,114,6,0,0, - 0,114,2,1,0,0,114,147,0,0,0,114,11,1,0,0, - 114,24,1,0,0,218,9,109,101,116,97,95,112,97,116,104, - 114,165,0,0,0,114,253,0,0,0,41,2,114,35,1,0, - 0,90,17,115,117,112,112,111,114,116,101,100,95,108,111,97, - 100,101,114,115,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,8,95,105,110,115,116,97,108,108,243,5,0, - 0,115,8,0,0,0,0,2,8,1,6,1,20,1,114,38, - 1,0,0,41,1,114,47,0,0,0,41,1,78,41,3,78, - 78,78,41,2,114,60,0,0,0,114,60,0,0,0,41,1, - 84,41,1,78,41,1,78,41,61,114,109,0,0,0,114,10, - 0,0,0,90,37,95,67,65,83,69,95,73,78,83,69,78, - 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, - 95,66,89,84,69,83,95,75,69,89,114,9,0,0,0,114, - 11,0,0,0,114,17,0,0,0,114,19,0,0,0,114,28, - 0,0,0,114,38,0,0,0,114,39,0,0,0,114,43,0, - 0,0,114,44,0,0,0,114,46,0,0,0,114,56,0,0, - 0,218,4,116,121,112,101,218,8,95,95,99,111,100,101,95, - 95,114,142,0,0,0,114,15,0,0,0,114,129,0,0,0, - 114,14,0,0,0,114,18,0,0,0,114,209,0,0,0,114, - 75,0,0,0,114,74,0,0,0,114,86,0,0,0,114,76, - 0,0,0,90,23,68,69,66,85,71,95,66,89,84,69,67, - 79,68,69,95,83,85,70,70,73,88,69,83,90,27,79,80, - 84,73,77,73,90,69,68,95,66,89,84,69,67,79,68,69, - 95,83,85,70,70,73,88,69,83,114,81,0,0,0,114,87, - 0,0,0,114,93,0,0,0,114,97,0,0,0,114,99,0, - 0,0,114,118,0,0,0,114,125,0,0,0,114,133,0,0, - 0,114,137,0,0,0,114,139,0,0,0,114,145,0,0,0, - 114,150,0,0,0,114,152,0,0,0,114,157,0,0,0,218, - 6,111,98,106,101,99,116,114,164,0,0,0,114,169,0,0, - 0,114,170,0,0,0,114,185,0,0,0,114,195,0,0,0, - 114,212,0,0,0,114,220,0,0,0,114,225,0,0,0,114, - 231,0,0,0,114,226,0,0,0,114,232,0,0,0,114,251, - 0,0,0,114,253,0,0,0,114,11,1,0,0,114,29,1, - 0,0,114,163,0,0,0,114,36,1,0,0,114,38,1,0, - 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,8,60,109,111,100,117,108,101,62,24, - 0,0,0,115,116,0,0,0,4,0,4,1,4,1,2,1, - 6,3,8,17,8,5,8,5,8,6,8,12,8,10,8,9, - 8,5,8,7,10,22,10,126,16,1,12,2,4,1,4,2, - 6,2,6,2,8,2,16,45,8,34,8,19,8,12,8,12, - 8,28,8,17,8,33,8,28,8,24,10,13,10,10,10,11, - 8,14,6,3,4,1,14,67,14,64,14,29,16,127,0,17, - 14,41,18,45,18,26,4,3,18,53,14,60,14,42,14,127, - 0,5,14,127,0,22,10,23,8,11,8,64, + 0,218,8,60,109,111,100,117,108,101,62,24,0,0,0,115, + 116,0,0,0,4,0,4,1,4,1,2,1,6,3,8,17, + 8,5,8,5,8,6,8,12,8,10,8,9,8,5,8,7, + 10,22,10,126,16,1,12,2,4,1,4,2,6,2,6,2, + 8,2,16,45,8,34,8,19,8,12,8,12,8,28,8,17, + 8,33,8,28,8,24,10,13,10,10,10,11,8,14,6,3, + 4,1,14,67,14,64,14,29,16,127,0,17,14,41,18,45, + 18,26,4,3,18,53,14,60,14,42,14,127,0,5,14,127, + 0,22,10,23,8,11,8,64, }; diff --git a/Python/peephole.c b/Python/peephole.c index 58171465633..49d62a2c342 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -173,8 +173,6 @@ copy_op_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned char op, new constant (c1, c2, ... cn) can be appended. Called with codestr pointing to the first LOAD_CONST. Bails out with no change if one or more of the LOAD_CONSTs is missing. - Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in" - test; for BUILD_SET it assembles a frozenset rather than a tuple. */ static Py_ssize_t fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, @@ -198,15 +196,6 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, PyTuple_SET_ITEM(newconst, i, constant); } - /* If it's a BUILD_SET, use the PyTuple we just built to create a - PyFrozenSet, and use that as the constant instead: */ - if (opcode == BUILD_SET) { - Py_SETREF(newconst, PyFrozenSet_New(newconst)); - if (newconst == NULL) { - return -1; - } - } - /* Append folded constant onto consts */ len_consts = PyList_GET_SIZE(consts); if (PyList_Append(consts, newconst)) { @@ -358,24 +347,15 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, CONST_STACK_POP(1); break; - /* Try to fold tuples of constants (includes a case for lists - and sets which are only used for "in" and "not in" tests). + /* Try to fold tuples of constants. Skip over BUILD_SEQN 1 UNPACK_SEQN 1. Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2. Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */ case BUILD_TUPLE: - case BUILD_LIST: - case BUILD_SET: j = get_arg(codestr, i); if (j > 0 && CONST_STACK_LEN() >= j) { h = lastn_const_start(codestr, op_start, j); - if ((opcode == BUILD_TUPLE && - ISBASICBLOCK(blocks, h, op_start)) || - ((opcode == BUILD_LIST || opcode == BUILD_SET) && - ((nextop==COMPARE_OP && - (_Py_OPARG(codestr[nexti]) == PyCmp_IN || - _Py_OPARG(codestr[nexti]) == PyCmp_NOT_IN)) || - nextop == GET_ITER) && ISBASICBLOCK(blocks, h, i + 1))) { + if (ISBASICBLOCK(blocks, h, op_start)) { h = fold_tuple_on_constants(codestr, h, i + 1, opcode, consts, CONST_STACK_LASTN(j), j); if (h >= 0) { @@ -387,8 +367,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } if (nextop != UNPACK_SEQUENCE || !ISBASICBLOCK(blocks, op_start, i + 1) || - j != get_arg(codestr, nexti) || - opcode == BUILD_SET) + j != get_arg(codestr, nexti)) break; if (j < 2) { fill_nops(codestr, op_start, nexti + 1); From webhook-mailer at python.org Thu Dec 14 17:33:04 2017 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Thu, 14 Dec 2017 22:33:04 -0000 Subject: [Python-checkins] bpo-32226: Implementation of PEP 560 (core components) (#4732) Message-ID: https://github.com/python/cpython/commit/2b5fd1e9ca9318673989e6ccac2c8acadc3809cd commit: 2b5fd1e9ca9318673989e6ccac2c8acadc3809cd branch: master author: Ivan Levkivskyi committer: GitHub date: 2017-12-14T23:32:56+01:00 summary: bpo-32226: Implementation of PEP 560 (core components) (#4732) This part of the PEP implementation adds support for __mro_entries__ and __class_getitem__ by updating __build_class__ and PyObject_GetItem. files: A Lib/test/test_genericclass.py A Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-42-58.bpo-32226.G8fqb6.rst M Lib/test/test_types.py M Lib/types.py M Objects/abstract.c M Objects/typeobject.c M Python/bltinmodule.c diff --git a/Lib/test/test_genericclass.py b/Lib/test/test_genericclass.py new file mode 100644 index 00000000000..214527b01fa --- /dev/null +++ b/Lib/test/test_genericclass.py @@ -0,0 +1,252 @@ +import unittest + + +class TestMROEntry(unittest.TestCase): + def test_mro_entry_signature(self): + tested = [] + class B: ... + class C: + def __mro_entries__(self, *args, **kwargs): + tested.extend([args, kwargs]) + return (C,) + c = C() + self.assertEqual(tested, []) + class D(B, c): ... + self.assertEqual(tested[0], ((B, c),)) + self.assertEqual(tested[1], {}) + + def test_mro_entry(self): + tested = [] + class A: ... + class B: ... + class C: + def __mro_entries__(self, bases): + tested.append(bases) + return (self.__class__,) + c = C() + self.assertEqual(tested, []) + class D(A, c, B): ... + self.assertEqual(tested[-1], (A, c, B)) + self.assertEqual(D.__bases__, (A, C, B)) + self.assertEqual(D.__orig_bases__, (A, c, B)) + self.assertEqual(D.__mro__, (D, A, C, B, object)) + d = D() + class E(d): ... + self.assertEqual(tested[-1], (d,)) + self.assertEqual(E.__bases__, (D,)) + + def test_mro_entry_none(self): + tested = [] + class A: ... + class B: ... + class C: + def __mro_entries__(self, bases): + tested.append(bases) + return () + c = C() + self.assertEqual(tested, []) + class D(A, c, B): ... + self.assertEqual(tested[-1], (A, c, B)) + self.assertEqual(D.__bases__, (A, B)) + self.assertEqual(D.__orig_bases__, (A, c, B)) + self.assertEqual(D.__mro__, (D, A, B, object)) + class E(c): ... + self.assertEqual(tested[-1], (c,)) + self.assertEqual(E.__bases__, (object,)) + self.assertEqual(E.__orig_bases__, (c,)) + self.assertEqual(E.__mro__, (E, object)) + + def test_mro_entry_with_builtins(self): + tested = [] + class A: ... + class C: + def __mro_entries__(self, bases): + tested.append(bases) + return (dict,) + c = C() + self.assertEqual(tested, []) + class D(A, c): ... + self.assertEqual(tested[-1], (A, c)) + self.assertEqual(D.__bases__, (A, dict)) + self.assertEqual(D.__orig_bases__, (A, c)) + self.assertEqual(D.__mro__, (D, A, dict, object)) + + def test_mro_entry_with_builtins_2(self): + tested = [] + class C: + def __mro_entries__(self, bases): + tested.append(bases) + return (C,) + c = C() + self.assertEqual(tested, []) + class D(c, dict): ... + self.assertEqual(tested[-1], (c, dict)) + self.assertEqual(D.__bases__, (C, dict)) + self.assertEqual(D.__orig_bases__, (c, dict)) + self.assertEqual(D.__mro__, (D, C, dict, object)) + + def test_mro_entry_errors(self): + class C_too_many: + def __mro_entries__(self, bases, something, other): + return () + c = C_too_many() + with self.assertRaises(TypeError): + class D(c): ... + class C_too_few: + def __mro_entries__(self): + return () + d = C_too_few() + with self.assertRaises(TypeError): + class D(d): ... + + def test_mro_entry_errors_2(self): + class C_not_callable: + __mro_entries__ = "Surprise!" + c = C_not_callable() + with self.assertRaises(TypeError): + class D(c): ... + class C_not_tuple: + def __mro_entries__(self): + return object + c = C_not_tuple() + with self.assertRaises(TypeError): + class D(c): ... + + def test_mro_entry_metaclass(self): + meta_args = [] + class Meta(type): + def __new__(mcls, name, bases, ns): + meta_args.extend([mcls, name, bases, ns]) + return super().__new__(mcls, name, bases, ns) + class A: ... + class C: + def __mro_entries__(self, bases): + return (A,) + c = C() + class D(c, metaclass=Meta): + x = 1 + self.assertEqual(meta_args[0], Meta) + self.assertEqual(meta_args[1], 'D') + self.assertEqual(meta_args[2], (A,)) + self.assertEqual(meta_args[3]['x'], 1) + self.assertEqual(D.__bases__, (A,)) + self.assertEqual(D.__orig_bases__, (c,)) + self.assertEqual(D.__mro__, (D, A, object)) + self.assertEqual(D.__class__, Meta) + + def test_mro_entry_type_call(self): + # Substitution should _not_ happen in direct type call + class C: + def __mro_entries__(self, bases): + return () + c = C() + with self.assertRaisesRegex(TypeError, + "MRO entry resolution; " + "use types.new_class()"): + type('Bad', (c,), {}) + + +class TestClassGetitem(unittest.TestCase): + def test_class_getitem(self): + getitem_args = [] + class C: + def __class_getitem__(*args, **kwargs): + getitem_args.extend([args, kwargs]) + return None + C[int, str] + self.assertEqual(getitem_args[0], (C, (int, str))) + self.assertEqual(getitem_args[1], {}) + + def test_class_getitem(self): + class C: + def __class_getitem__(cls, item): + return f'C[{item.__name__}]' + self.assertEqual(C[int], 'C[int]') + self.assertEqual(C[C], 'C[C]') + + def test_class_getitem_inheritance(self): + class C: + def __class_getitem__(cls, item): + return f'{cls.__name__}[{item.__name__}]' + class D(C): ... + self.assertEqual(D[int], 'D[int]') + self.assertEqual(D[D], 'D[D]') + + def test_class_getitem_inheritance_2(self): + class C: + def __class_getitem__(cls, item): + return 'Should not see this' + class D(C): + def __class_getitem__(cls, item): + return f'{cls.__name__}[{item.__name__}]' + self.assertEqual(D[int], 'D[int]') + self.assertEqual(D[D], 'D[D]') + + def test_class_getitem_patched(self): + class C: + def __init_subclass__(cls): + def __class_getitem__(cls, item): + return f'{cls.__name__}[{item.__name__}]' + cls.__class_getitem__ = __class_getitem__ + class D(C): ... + self.assertEqual(D[int], 'D[int]') + self.assertEqual(D[D], 'D[D]') + + def test_class_getitem_with_builtins(self): + class A(dict): + called_with = None + + def __class_getitem__(cls, item): + cls.called_with = item + class B(A): + pass + self.assertIs(B.called_with, None) + B[int] + self.assertIs(B.called_with, int) + + def test_class_getitem_errors(self): + class C_too_few: + def __class_getitem__(cls): + return None + with self.assertRaises(TypeError): + C_too_few[int] + class C_too_many: + def __class_getitem__(cls, one, two): + return None + with self.assertRaises(TypeError): + C_too_many[int] + + def test_class_getitem_errors_2(self): + class C: + def __class_getitem__(cls, item): + return None + with self.assertRaises(TypeError): + C()[int] + class E: ... + e = E() + e.__class_getitem__ = lambda cls, item: 'This will not work' + with self.assertRaises(TypeError): + e[int] + class C_not_callable: + __class_getitem__ = "Surprise!" + with self.assertRaises(TypeError): + C_not_callable[int] + + def test_class_getitem_metaclass(self): + class Meta(type): + def __class_getitem__(cls, item): + return f'{cls.__name__}[{item.__name__}]' + self.assertEqual(Meta[int], 'Meta[int]') + + def test_class_getitem_metaclass_2(self): + class Meta(type): + def __getitem__(cls, item): + return 'from metaclass' + class C(metaclass=Meta): + def __class_getitem__(cls, item): + return 'from __class_getitem__' + self.assertEqual(C[int], 'from metaclass') + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 28133a3560f..47488a615b1 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -844,6 +844,68 @@ def func(ns): self.assertEqual(C.y, 1) self.assertEqual(C.z, 2) + def test_new_class_with_mro_entry(self): + class A: pass + class C: + def __mro_entries__(self, bases): + return (A,) + c = C() + D = types.new_class('D', (c,), {}) + self.assertEqual(D.__bases__, (A,)) + self.assertEqual(D.__orig_bases__, (c,)) + self.assertEqual(D.__mro__, (D, A, object)) + + def test_new_class_with_mro_entry_none(self): + class A: pass + class B: pass + class C: + def __mro_entries__(self, bases): + return () + c = C() + D = types.new_class('D', (A, c, B), {}) + self.assertEqual(D.__bases__, (A, B)) + self.assertEqual(D.__orig_bases__, (A, c, B)) + self.assertEqual(D.__mro__, (D, A, B, object)) + + def test_new_class_with_mro_entry_error(self): + class A: pass + class C: + def __mro_entries__(self, bases): + return A + c = C() + with self.assertRaises(TypeError): + types.new_class('D', (c,), {}) + + def test_new_class_with_mro_entry_multiple(self): + class A1: pass + class A2: pass + class B1: pass + class B2: pass + class A: + def __mro_entries__(self, bases): + return (A1, A2) + class B: + def __mro_entries__(self, bases): + return (B1, B2) + D = types.new_class('D', (A(), B()), {}) + self.assertEqual(D.__bases__, (A1, A2, B1, B2)) + + def test_new_class_with_mro_entry_multiple_2(self): + class A1: pass + class A2: pass + class A3: pass + class B1: pass + class B2: pass + class A: + def __mro_entries__(self, bases): + return (A1, A2, A3) + class B: + def __mro_entries__(self, bases): + return (B1, B2) + class C: pass + D = types.new_class('D', (A(), C, B()), {}) + self.assertEqual(D.__bases__, (A1, A2, A3, C, B1, B2)) + # Many of the following tests are derived from test_descr.py def test_prepare_class(self): # Basic test of metaclass derivation @@ -886,6 +948,28 @@ def __prepare__(*args): class Bar(metaclass=BadMeta()): pass + def test_resolve_bases(self): + class A: pass + class B: pass + class C: + def __mro_entries__(self, bases): + if A in bases: + return () + return (A,) + c = C() + self.assertEqual(types.resolve_bases(()), ()) + self.assertEqual(types.resolve_bases((c,)), (A,)) + self.assertEqual(types.resolve_bases((C,)), (C,)) + self.assertEqual(types.resolve_bases((A, C)), (A, C)) + self.assertEqual(types.resolve_bases((c, A)), (A,)) + self.assertEqual(types.resolve_bases((A, c)), (A,)) + x = (A,) + y = (C,) + z = (A, C) + t = (A, C, B) + for bases in [x, y, z, t]: + self.assertIs(types.resolve_bases(bases), bases) + def test_metaclass_derivation(self): # issue1294232: correct metaclass calculation new_calls = [] # to check the order of __new__ calls diff --git a/Lib/types.py b/Lib/types.py index 336918fea09..c5976f3057f 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -60,10 +60,34 @@ def _m(self): pass # 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.""" - meta, ns, kwds = prepare_class(name, bases, kwds) + resolved_bases = resolve_bases(bases) + meta, ns, kwds = prepare_class(name, resolved_bases, kwds) if exec_body is not None: exec_body(ns) - return meta(name, bases, ns, **kwds) + if resolved_bases is not bases: + ns['__orig_bases__'] = bases + return meta(name, resolved_bases, ns, **kwds) + +def resolve_bases(bases): + """Resolve MRO entries dynamically as specified by PEP 560.""" + new_bases = list(bases) + updated = False + shift = 0 + for i, base in enumerate(bases): + if isinstance(base, type): + continue + if not hasattr(base, "__mro_entries__"): + continue + new_base = base.__mro_entries__(bases) + updated = True + if not isinstance(new_base, tuple): + raise TypeError("__mro_entries__ must return a tuple") + else: + new_bases[i+shift:i+shift+1] = new_base + shift += len(new_base) - 1 + if not updated: + return bases + return tuple(new_bases) def prepare_class(name, bases=(), kwds=None): """Call the __prepare__ method of the appropriate metaclass. diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-42-58.bpo-32226.G8fqb6.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-42-58.bpo-32226.G8fqb6.rst new file mode 100644 index 00000000000..97954fd1bb0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-05-21-42-58.bpo-32226.G8fqb6.rst @@ -0,0 +1,2 @@ +PEP 560: Add support for __mro_entries__ and __class_getitem__. Implemented +by Ivan Levkivskyi. diff --git a/Objects/abstract.c b/Objects/abstract.c index 3cb7a32b01e..0105c5d1696 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -168,6 +168,21 @@ PyObject_GetItem(PyObject *o, PyObject *key) "be integer, not '%.200s'", key); } + if (PyType_Check(o)) { + PyObject *meth, *result, *stack[2] = {o, key}; + _Py_IDENTIFIER(__class_getitem__); + meth = _PyObject_GetAttrId(o, &PyId___class_getitem__); + if (meth) { + result = _PyObject_FastCall(meth, stack, 2); + Py_DECREF(meth); + return result; + } + else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + return NULL; + } + PyErr_Clear(); + } + return type_error("'%.200s' object is not subscriptable", o); } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 73f94e76c90..5403ecb04f9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2377,6 +2377,27 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) nbases = 1; } else { + _Py_IDENTIFIER(__mro_entries__); + for (i = 0; i < nbases; i++) { + tmp = PyTuple_GET_ITEM(bases, i); + if (PyType_Check(tmp)) { + continue; + } + tmp = _PyObject_GetAttrId(tmp, &PyId___mro_entries__); + if (tmp != NULL) { + PyErr_SetString(PyExc_TypeError, + "type() doesn't support MRO entry resolution; " + "use types.new_class()"); + Py_DECREF(tmp); + return NULL; + } + else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + else { + return NULL; + } + } /* Search the bases for the proper metatype to deal with this: */ winner = _PyType_CalculateMetaclass(metatype, bases); if (winner == NULL) { diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 23d7aa45683..a3632115d3b 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -37,6 +37,7 @@ _Py_IDENTIFIER(__builtins__); _Py_IDENTIFIER(__dict__); _Py_IDENTIFIER(__prepare__); _Py_IDENTIFIER(__round__); +_Py_IDENTIFIER(__mro_entries__); _Py_IDENTIFIER(encoding); _Py_IDENTIFIER(errors); _Py_IDENTIFIER(fileno); @@ -49,12 +50,86 @@ _Py_IDENTIFIER(stderr); #include "clinic/bltinmodule.c.h" +static PyObject* +update_bases(PyObject *bases, PyObject *const *args, int nargs) +{ + int i, j; + PyObject *base, *meth, *new_base, *result, *new_bases = NULL; + PyObject *stack[1] = {bases}; + assert(PyTuple_Check(bases)); + + for (i = 0; i < nargs; i++) { + base = args[i]; + if (PyType_Check(base)) { + if (new_bases) { + /* If we already have made a replacement, then we append every normal base, + otherwise just skip it. */ + if (PyList_Append(new_bases, base) < 0) { + goto error; + } + } + continue; + } + meth = _PyObject_GetAttrId(base, &PyId___mro_entries__); + if (!meth) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + goto error; + } + PyErr_Clear(); + if (new_bases) { + if (PyList_Append(new_bases, base) < 0) { + goto error; + } + } + continue; + } + new_base = _PyObject_FastCall(meth, stack, 1); + Py_DECREF(meth); + if (!new_base) { + goto error; + } + if (!PyTuple_Check(new_base)) { + PyErr_SetString(PyExc_TypeError, + "__mro_entries__ must return a tuple"); + Py_DECREF(new_base); + goto error; + } + if (!new_bases) { + /* If this is a first successful replacement, create new_bases list and + copy previously encountered bases. */ + if (!(new_bases = PyList_New(i))) { + goto error; + } + for (j = 0; j < i; j++) { + base = args[j]; + PyList_SET_ITEM(new_bases, j, base); + Py_INCREF(base); + } + } + j = PyList_GET_SIZE(new_bases); + if (PyList_SetSlice(new_bases, j, j, new_base) < 0) { + goto error; + } + Py_DECREF(new_base); + } + if (!new_bases) { + return bases; + } + result = PyList_AsTuple(new_bases); + Py_DECREF(new_bases); + return result; + +error: + Py_XDECREF(new_bases); + return NULL; +} + /* AC: cannot convert yet, waiting for *args support */ static PyObject * builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { - PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns; + PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *orig_bases; PyObject *cls = NULL, *cell = NULL; int isclass = 0; /* initialize to prevent gcc warning */ @@ -75,10 +150,16 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs, "__build_class__: name is not a string"); return NULL; } - bases = _PyStack_AsTupleSlice(args, nargs, 2, nargs); - if (bases == NULL) + orig_bases = _PyStack_AsTupleSlice(args, nargs, 2, nargs); + if (orig_bases == NULL) return NULL; + bases = update_bases(orig_bases, args + 2, nargs - 2); + if (bases == NULL) { + Py_DECREF(orig_bases); + return NULL; + } + if (kwnames == NULL) { meta = NULL; mkw = NULL; @@ -171,6 +252,11 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs, NULL, 0, NULL, 0, NULL, 0, NULL, PyFunction_GET_CLOSURE(func)); if (cell != NULL) { + if (bases != orig_bases) { + if (PyMapping_SetItemString(ns, "__orig_bases__", orig_bases) < 0) { + goto error; + } + } PyObject *margs[3] = {name, bases, ns}; cls = _PyObject_FastCallDict(meta, margs, 3, mkw); if (cls != NULL && PyType_Check(cls) && PyCell_Check(cell)) { @@ -209,6 +295,9 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs, Py_DECREF(meta); Py_XDECREF(mkw); Py_DECREF(bases); + if (bases != orig_bases) { + Py_DECREF(orig_bases); + } return cls; } From webhook-mailer at python.org Thu Dec 14 17:46:50 2017 From: webhook-mailer at python.org (Fred Drake) Date: Thu, 14 Dec 2017 22:46:50 -0000 Subject: [Python-checkins] bpo-32143: add f_fsid to os.statvfs() (#4571) Message-ID: https://github.com/python/cpython/commit/96a5e50a5de3683b2afd6d680c7ecc4b525986f6 commit: 96a5e50a5de3683b2afd6d680c7ecc4b525986f6 branch: master author: Giuseppe Scrivano committer: Fred Drake date: 2017-12-14T17:46:46-05:00 summary: bpo-32143: add f_fsid to os.statvfs() (#4571) Signed-off-by: Giuseppe Scrivano files: A Misc/NEWS.d/next/Library/2017-11-26-17-28-26.bpo-32143.o7YdXL.rst M Doc/library/os.rst M Lib/test/test_os.py M Modules/posixmodule.c diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 95c81137230..a24934ceb7b 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2436,7 +2436,7 @@ features: correspond to the members of the :c:type:`statvfs` structure, namely: :attr:`f_bsize`, :attr:`f_frsize`, :attr:`f_blocks`, :attr:`f_bfree`, :attr:`f_bavail`, :attr:`f_files`, :attr:`f_ffree`, :attr:`f_favail`, - :attr:`f_flag`, :attr:`f_namemax`. + :attr:`f_flag`, :attr:`f_namemax`, :attr:`f_fsid`. Two module-level constants are defined for the :attr:`f_flag` attribute's bit-flags: if :const:`ST_RDONLY` is set, the filesystem is mounted @@ -2471,6 +2471,9 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionadded:: 3.7 + Added :attr:`f_fsid`. + .. data:: supports_dir_fd diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 22412569092..f235f801e03 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -352,6 +352,11 @@ def test_statvfs_attributes(self): for value, member in enumerate(members): self.assertEqual(getattr(result, 'f_' + member), result[value]) + self.assertTrue(isinstance(result.f_fsid, int)) + + # Test that the size of the tuple doesn't change + self.assertEqual(len(result), 10) + # Make sure that assignment really fails try: result.f_bfree = 1 diff --git a/Misc/NEWS.d/next/Library/2017-11-26-17-28-26.bpo-32143.o7YdXL.rst b/Misc/NEWS.d/next/Library/2017-11-26-17-28-26.bpo-32143.o7YdXL.rst new file mode 100644 index 00000000000..f416ec504ec --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-26-17-28-26.bpo-32143.o7YdXL.rst @@ -0,0 +1 @@ +os.statvfs() includes the f_fsid field from statvfs(2) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index fb879e3821a..448d4b7428e 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1860,6 +1860,7 @@ static PyStructSequence_Field statvfs_result_fields[] = { {"f_favail", }, {"f_flag", }, {"f_namemax",}, + {"f_fsid", }, {0} }; @@ -9324,6 +9325,7 @@ _pystatvfs_fromstructstatvfs(struct statvfs st) { PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); #endif + PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid)); if (PyErr_Occurred()) { Py_DECREF(v); return NULL; From webhook-mailer at python.org Thu Dec 14 18:51:25 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 14 Dec 2017 23:51:25 -0000 Subject: [Python-checkins] bpo-32329: Fix -R option for hash randomization (#4873) Message-ID: https://github.com/python/cpython/commit/358e5e17a51ba00742bfaee4557a94c3c4179c22 commit: 358e5e17a51ba00742bfaee4557a94c3c4179c22 branch: master author: Victor Stinner committer: GitHub date: 2017-12-15T00:51:22+01:00 summary: bpo-32329: Fix -R option for hash randomization (#4873) bpo-32329, bpo-32030: * The -R option now turns on hash randomization when the PYTHONHASHSEED environment variable is set to 0 Previously, the option was ignored. * sys.flags.hash_randomization is now properly set to 0 when hash randomization is turned off by PYTHONHASHSEED=0. * _PyCoreConfig_ReadEnv() now reads the PYTHONHASHSEED environment variable. _Py_HashRandomization_Init() now only apply the configuration, it doesn't read PYTHONHASHSEED anymore. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-13-04.bpo-32329.q47IN2.rst M Doc/using/cmdline.rst M Include/pylifecycle.h M Lib/test/test_cmd_line.py M Modules/main.c M Python/bootstrap_hash.c diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 5cb90717705..598eb2583d3 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -277,8 +277,9 @@ Miscellaneous options .. cmdoption:: -R - Kept for compatibility. On Python 3.3 and greater, hash randomization is - turned on by default. + Turn on hash randomization. This option only has an effect if the + :envvar:`PYTHONHASHSEED` environment variable is set to ``0``, since hash + randomization is enabled by default. On previous versions of Python, this option turns on hash randomization, so that the :meth:`__hash__` values of str, bytes and datetime diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 61ed6ccf021..0416bfae0ea 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -136,7 +136,13 @@ PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void); PyAPI_FUNC(int) _PyFrame_Init(void); PyAPI_FUNC(int) _PyFloat_Init(void); PyAPI_FUNC(int) PyByteArray_Init(void); -PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(_PyCoreConfig *core_config); +PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(const _PyCoreConfig *); +#endif +#ifdef Py_BUILD_CORE +PyAPI_FUNC(int) _Py_ReadHashSeed( + const char *seed_text, + int *use_hash_seed, + unsigned long *hash_seed); #endif /* Various internal finalizers */ diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 2aff51bdc13..2b14c301c7d 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -432,8 +432,16 @@ def test_hash_randomization(self): # Verify that sys.flags contains hash_randomization code = 'import sys; print("random is", sys.flags.hash_randomization)' - rc, out, err = assert_python_ok('-c', code) - self.assertEqual(rc, 0) + rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='') + self.assertIn(b'random is 1', out) + + rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='random') + self.assertIn(b'random is 1', out) + + rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='0') + self.assertIn(b'random is 0', out) + + rc, out, err = assert_python_ok('-R', '-c', code, PYTHONHASHSEED='0') self.assertIn(b'random is 1', out) def test_del___main__(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-13-04.bpo-32329.q47IN2.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-13-04.bpo-32329.q47IN2.rst new file mode 100644 index 00000000000..86bcf234477 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-13-04.bpo-32329.q47IN2.rst @@ -0,0 +1,5 @@ +The :option:`-R` option now turns on hash randomization when the +:envvar:`PYTHONHASHSEED` environment variable is set to ``0``. Previously, +the option was ignored. Moreover, ``sys.flags.hash_randomization`` is now +properly set to 0 when hash randomization is turned off by +``PYTHONHASHSEED=0``. diff --git a/Modules/main.c b/Modules/main.c index 6db7e5f7088..e1a2f98dc6a 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -726,7 +726,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain) break; case 'R': - /* Ignored */ + pymain->core_config.use_hash_seed = 0; break; /* This space reserved for other options */ @@ -1293,6 +1293,10 @@ pymain_set_global_config(_PyMain *pymain) Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; Py_UTF8Mode = pymain->core_config.utf8_mode; + + /* Random or non-zero hash seed */ + Py_HashRandomizationFlag = (pymain->core_config.use_hash_seed == 0 || + pymain->core_config.hash_seed != 0); } @@ -1694,6 +1698,24 @@ config_init_home(_PyCoreConfig *config) } +static _PyInitError +config_init_hash_seed(_PyCoreConfig *config) +{ + if (config->use_hash_seed < 0) { + const char *seed_text = pymain_get_env_var("PYTHONHASHSEED"); + int use_hash_seed; + unsigned long hash_seed; + if (_Py_ReadHashSeed(seed_text, &use_hash_seed, &hash_seed) < 0) { + return _Py_INIT_USER_ERR("PYTHONHASHSEED must be \"random\" " + "or an integer in range [0; 4294967295]"); + } + config->use_hash_seed = use_hash_seed; + config->hash_seed = hash_seed; + } + return _Py_INIT_OK(); +} + + _PyInitError _PyCoreConfig_ReadEnv(_PyCoreConfig *config) { @@ -1712,6 +1734,11 @@ _PyCoreConfig_ReadEnv(_PyCoreConfig *config) return err; } + err = config_init_hash_seed(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + return _Py_INIT_OK(); } @@ -1777,12 +1804,6 @@ pymain_parse_envvars(_PyMain *pymain) /* Get environment variables */ pymain_set_flags_from_env(pymain); - /* The variable is only tested for existence here; - _Py_HashRandomization_Init will check its value further. */ - if (pymain_get_env_var("PYTHONHASHSEED")) { - Py_HashRandomizationFlag = 1; - } - if (pymain_warnings_envvar(pymain) < 0) { return -1; } diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 2762f4656e2..9fd5cfb200e 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -533,9 +533,10 @@ _PyOS_URandomNonblock(void *buffer, Py_ssize_t size) return pyurandom(buffer, size, 0, 1); } -int Py_ReadHashSeed(const char *seed_text, - int *use_hash_seed, - unsigned long *hash_seed) +int +_Py_ReadHashSeed(const char *seed_text, + int *use_hash_seed, + unsigned long *hash_seed) { Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc)); /* Convert a text seed to a numeric one */ @@ -561,9 +562,9 @@ int Py_ReadHashSeed(const char *seed_text, return 0; } -static _PyInitError -init_hash_secret(int use_hash_seed, - unsigned long hash_seed) + +_PyInitError +_Py_HashRandomization_Init(const _PyCoreConfig *config) { void *secret = &_Py_HashSecret; Py_ssize_t secret_size = sizeof(_Py_HashSecret_t); @@ -573,14 +574,14 @@ init_hash_secret(int use_hash_seed, } _Py_HashSecret_Initialized = 1; - if (use_hash_seed) { - if (hash_seed == 0) { + if (config->use_hash_seed) { + if (config->hash_seed == 0) { /* disable the randomized hash */ memset(secret, 0, secret_size); } else { /* use the specified hash seed */ - lcg_urandom(hash_seed, secret, secret_size); + lcg_urandom(config->hash_seed, secret, secret_size); } } else { @@ -601,24 +602,6 @@ init_hash_secret(int use_hash_seed, return _Py_INIT_OK(); } -_PyInitError -_Py_HashRandomization_Init(_PyCoreConfig *core_config) -{ - const char *seed_text; - int use_hash_seed = core_config->use_hash_seed; - unsigned long hash_seed = core_config->hash_seed; - - if (use_hash_seed < 0) { - seed_text = Py_GETENV("PYTHONHASHSEED"); - if (Py_ReadHashSeed(seed_text, &use_hash_seed, &hash_seed) < 0) { - return _Py_INIT_USER_ERR("PYTHONHASHSEED must be \"random\" " - "or an integer in range [0; 4294967295]"); - } - core_config->use_hash_seed = use_hash_seed; - core_config->hash_seed = hash_seed; - } - return init_hash_secret(use_hash_seed, hash_seed); -} void _Py_HashRandomization_Fini(void) From webhook-mailer at python.org Thu Dec 14 19:39:51 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 00:39:51 -0000 Subject: [Python-checkins] bpo-32329: Fix sys.flags.hash_randomization (#4875) Message-ID: https://github.com/python/cpython/commit/22097aaa77b4f0473552fe840358d77e5b9a253f commit: 22097aaa77b4f0473552fe840358d77e5b9a253f branch: 3.6 author: Victor Stinner committer: GitHub date: 2017-12-15T01:39:48+01:00 summary: bpo-32329: Fix sys.flags.hash_randomization (#4875) sys.flags.hash_randomization is now properly set to 0 when hash randomization is turned off by PYTHONHASHSEED=0. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-55-35.bpo-32329.XL1O99.rst M Lib/test/test_cmd_line.py M Modules/main.c M Python/pylifecycle.c M Python/random.c diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index ae2bcd43754..98441b0f4a5 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -426,10 +426,15 @@ def test_hash_randomization(self): # Verify that sys.flags contains hash_randomization code = 'import sys; print("random is", sys.flags.hash_randomization)' - rc, out, err = assert_python_ok('-c', code) - self.assertEqual(rc, 0) + rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='') self.assertIn(b'random is 1', out) + rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='random') + self.assertIn(b'random is 1', out) + + rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='0') + self.assertIn(b'random is 0', out) + def test_del___main__(self): # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a # borrowed reference to the dict of __main__ module and later modify diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-55-35.bpo-32329.XL1O99.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-55-35.bpo-32329.XL1O99.rst new file mode 100644 index 00000000000..36ca84e6eb4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-00-55-35.bpo-32329.XL1O99.rst @@ -0,0 +1,2 @@ +``sys.flags.hash_randomization`` is now properly set to 0 when hash +randomization is turned off by ``PYTHONHASHSEED=0``. diff --git a/Modules/main.c b/Modules/main.c index b0fb78f887a..3ac405c0bd9 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -394,7 +394,6 @@ Py_Main(int argc, wchar_t **argv) exit(1); } - Py_HashRandomizationFlag = 1; _PyRandom_Init(); PySys_ResetWarnOptions(); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 640271fd20b..ecfdfee218d 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -330,10 +330,6 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p); if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0') Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p); - /* The variable is only tested for existence here; _PyRandom_Init will - check its value further. */ - if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0') - Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p); #ifdef MS_WINDOWS if ((p = Py_GETENV("PYTHONLEGACYWINDOWSFSENCODING")) && *p != '\0') Py_LegacyWindowsFSEncodingFlag = add_flag(Py_LegacyWindowsFSEncodingFlag, p); diff --git a/Python/random.c b/Python/random.c index c97d5e71002..e0ee153ec4a 100644 --- a/Python/random.c +++ b/Python/random.c @@ -565,9 +565,11 @@ _PyRandom_Init(void) if (seed == 0) { /* disable the randomized hash */ memset(secret, 0, secret_size); + Py_HashRandomizationFlag = 0; } else { lcg_urandom(seed, secret, secret_size); + Py_HashRandomizationFlag = 1; } } else { @@ -582,6 +584,7 @@ _PyRandom_Init(void) if (res < 0) { Py_FatalError("failed to get random numbers to initialize Python"); } + Py_HashRandomizationFlag = 1; } } From webhook-mailer at python.org Thu Dec 14 19:46:05 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 00:46:05 -0000 Subject: [Python-checkins] bpo-32030: Add _PyCoreConfig_Copy() (#4874) Message-ID: https://github.com/python/cpython/commit/da273412c4374de07a500e7f23f89a6bb7527398 commit: da273412c4374de07a500e7f23f89a6bb7527398 branch: master author: Victor Stinner committer: GitHub date: 2017-12-15T01:46:02+01:00 summary: bpo-32030: Add _PyCoreConfig_Copy() (#4874) Each interpreter now has its core_config and main_config copy: * Add _PyCoreConfig_Copy() and _PyMainInterpreterConfig_Copy() * Move _PyCoreConfig_Read(), _PyCoreConfig_Clear() and _PyMainInterpreterConfig_Clear() from Python/pylifecycle.c to Modules/main.c * Fix _Py_InitializeEx_Private(): call _PyCoreConfig_ReadEnv() before _Py_InitializeCore() files: M Include/pylifecycle.h M Modules/main.c M Python/pylifecycle.c M Python/pystate.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 0416bfae0ea..39339da45af 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -57,9 +57,15 @@ PyAPI_FUNC(int) _Py_IsCoreInitialized(void); PyAPI_FUNC(_PyInitError) _PyCoreConfig_ReadEnv(_PyCoreConfig *); PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *); PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); +PyAPI_FUNC(int) _PyCoreConfig_Copy( + _PyCoreConfig *config, + const _PyCoreConfig *config2); PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *, _PyCoreConfig *); PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *); +PyAPI_FUNC(int) _PyMainInterpreterConfig_Copy( + _PyMainInterpreterConfig *config, + const _PyMainInterpreterConfig *config2); PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *); #endif diff --git a/Modules/main.c b/Modules/main.c index e1a2f98dc6a..8c4219c7ec3 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1914,6 +1914,154 @@ pymain_parse_cmdline_envvars(_PyMain *pymain) } +/* Read configuration settings from standard locations + * + * This function doesn't make any changes to the interpreter state - it + * merely populates any missing configuration settings. This allows an + * embedding application to completely override a config option by + * setting it before calling this function, or else modify the default + * setting before passing the fully populated config to Py_EndInitialization. + * + * More advanced selective initialization tricks are possible by calling + * this function multiple times with various preconfigured settings. + */ + +_PyInitError +_PyCoreConfig_Read(_PyCoreConfig *config) +{ + if (config->program_name == NULL) { +#ifdef MS_WINDOWS + const wchar_t *program_name = L"python"; +#else + const wchar_t *program_name = L"python3"; +#endif + config->program_name = _PyMem_RawWcsdup(program_name); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + + return _Py_INIT_OK(); +} + + +void +_PyCoreConfig_Clear(_PyCoreConfig *config) +{ +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->module_search_path_env); + CLEAR(config->home); + CLEAR(config->program_name); +#undef CLEAR +} + + +int +_PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) +{ + _PyCoreConfig_Clear(config); + +#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR + COPY_ATTR(ignore_environment); + COPY_ATTR(use_hash_seed); + COPY_ATTR(hash_seed); + COPY_ATTR(_disable_importlib); + COPY_ATTR(allocator); + COPY_ATTR(dev_mode); + COPY_ATTR(faulthandler); + COPY_ATTR(tracemalloc); + COPY_ATTR(import_time); + COPY_ATTR(show_ref_count); + COPY_ATTR(show_alloc_count); + COPY_ATTR(dump_refs); + COPY_ATTR(malloc_stats); + COPY_ATTR(utf8_mode); +#undef COPY_ATTR + +#define COPY_STR_ATTR(ATTR) \ + do { \ + if (config2->ATTR != NULL) { \ + config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \ + if (config->ATTR == NULL) { \ + return -1; \ + } \ + } \ + } while (0) + + COPY_STR_ATTR(module_search_path_env); + COPY_STR_ATTR(home); + COPY_STR_ATTR(program_name); +#undef COPY_STR_ATTR + return 0; +} + + +void +_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) +{ + Py_CLEAR(config->argv); + Py_CLEAR(config->module_search_path); + Py_CLEAR(config->warnoptions); + Py_CLEAR(config->xoptions); +} + + +static PyObject* +config_copy_attr(PyObject *obj) +{ + if (PyUnicode_Check(obj)) { + Py_INCREF(obj); + return obj; + } + else if (PyList_Check(obj)) { + return PyList_GetSlice(obj, 0, Py_SIZE(obj)); + } + else if (PyDict_Check(obj)) { + /* The dict type is used for xoptions. Make the assumption that keys + and values are immutables */ + return PyDict_Copy(obj); + } + else { + PyErr_Format(PyExc_TypeError, + "cannot copy config attribute of type %.200s", + Py_TYPE(obj)->tp_name); + return NULL; + } +} + + +int +_PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config, + const _PyMainInterpreterConfig *config2) +{ + _PyMainInterpreterConfig_Clear(config); + +#define COPY_ATTR(ATTR) \ + do { \ + if (config2->ATTR != NULL) { \ + config->ATTR = config_copy_attr(config2->ATTR); \ + if (config->ATTR == NULL) { \ + return -1; \ + } \ + } \ + } while (0) + + COPY_ATTR(argv); + COPY_ATTR(module_search_path); + COPY_ATTR(warnoptions); + COPY_ATTR(xoptions); +#undef COPY_ATTR + return 0; +} + + + + static PyObject * config_create_path_list(const wchar_t *path, wchar_t delim) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index d813ddd6715..830f89d0d41 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -607,13 +607,13 @@ _Py_SetLocaleFromEnv(int category) */ _PyInitError -_Py_InitializeCore(const _PyCoreConfig *config) +_Py_InitializeCore(const _PyCoreConfig *core_config) { + assert(core_config != NULL); + PyInterpreterState *interp; PyThreadState *tstate; PyObject *bimod, *sysmod, *pstderr; - _PyCoreConfig core_config = _PyCoreConfig_INIT; - _PyMainInterpreterConfig preinit_config = _PyMainInterpreterConfig_INIT; _PyInitError err; err = _PyRuntime_Initialize(); @@ -621,11 +621,7 @@ _Py_InitializeCore(const _PyCoreConfig *config) return err; } - if (config != NULL) { - core_config = *config; - } - - if (_PyMem_SetupAllocators(core_config.allocator) < 0) { + if (_PyMem_SetupAllocators(core_config->allocator) < 0) { return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator"); } @@ -655,12 +651,12 @@ _Py_InitializeCore(const _PyCoreConfig *config) _emit_stderr_warning_for_legacy_locale(); #endif - err = _Py_HashRandomization_Init(&core_config); + err = _Py_HashRandomization_Init(core_config); if (_Py_INIT_FAILED(err)) { return err; } - if (!core_config.use_hash_seed || core_config.hash_seed) { + if (!core_config->use_hash_seed || core_config->hash_seed) { /* Random or non-zero hash seed */ Py_HashRandomizationFlag = 1; } @@ -671,10 +667,13 @@ _Py_InitializeCore(const _PyCoreConfig *config) } interp = PyInterpreterState_New(); - if (interp == NULL) + if (interp == NULL) { return _Py_INIT_ERR("can't make main interpreter"); - interp->core_config = core_config; - interp->config = preinit_config; + } + + if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { + return _Py_INIT_ERR("failed to copy core config"); + } tstate = PyThreadState_New(interp); if (tstate == NULL) @@ -779,62 +778,6 @@ _Py_InitializeCore(const _PyCoreConfig *config) return _Py_INIT_OK(); } -/* Read configuration settings from standard locations - * - * This function doesn't make any changes to the interpreter state - it - * merely populates any missing configuration settings. This allows an - * embedding application to completely override a config option by - * setting it before calling this function, or else modify the default - * setting before passing the fully populated config to Py_EndInitialization. - * - * More advanced selective initialization tricks are possible by calling - * this function multiple times with various preconfigured settings. - */ - -_PyInitError -_PyCoreConfig_Read(_PyCoreConfig *config) -{ - if (config->program_name == NULL) { -#ifdef MS_WINDOWS - const wchar_t *program_name = L"python"; -#else - const wchar_t *program_name = L"python3"; -#endif - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } - - return _Py_INIT_OK(); -} - -void -_PyCoreConfig_Clear(_PyCoreConfig *config) -{ -#define CLEAR(ATTR) \ - do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ - } while (0) - - CLEAR(config->module_search_path_env); - CLEAR(config->home); - CLEAR(config->program_name); -#undef CLEAR -} - - -void -_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) -{ - Py_CLEAR(config->argv); - Py_CLEAR(config->module_search_path); - Py_CLEAR(config->warnoptions); - Py_CLEAR(config->xoptions); -} - - /* Update interpreter state based on supplied configuration settings * * After calling this function, most of the restrictions on the interpreter @@ -869,7 +812,9 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return _Py_INIT_ERR("failed to get interpreter"); /* Now finish configuring the main interpreter */ - interp->config = *config; + if (_PyMainInterpreterConfig_Copy(&interp->config, config) < 0) { + return _Py_INIT_ERR("failed to copy main interpreter config"); + } if (interp->core_config._disable_importlib) { /* Special mode for freeze_importlib: run with no import system @@ -906,8 +851,9 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) } } - if (_PySys_EndInit(interp->sysdict) < 0) + if (_PySys_EndInit(interp->sysdict) < 0) { return _Py_INIT_ERR("can't finish initializing sys"); + } err = initexternalimport(interp); if (_Py_INIT_FAILED(err)) { @@ -979,12 +925,12 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) core_config._disable_importlib = !install_importlib; config.install_signal_handlers = install_sigs; - err = _Py_InitializeCore(&core_config); + err = _PyCoreConfig_ReadEnv(&core_config); if (_Py_INIT_FAILED(err)) { goto done; } - err = _PyCoreConfig_ReadEnv(&core_config); + err = _Py_InitializeCore(&core_config); if (_Py_INIT_FAILED(err)) { goto done; } @@ -1118,9 +1064,11 @@ Py_FinalizeEx(void) tstate = PyThreadState_GET(); interp = tstate->interp; - /* Copy the core config to be able to use it even - after PyInterpreterState_Delete() */ - _PyCoreConfig core_config = interp->core_config; + /* Copy the core config, PyInterpreterState_Delete() free + the core config memory */ + int show_ref_count = interp->core_config.show_ref_count; + int dump_refs = interp->core_config.dump_refs; + int malloc_stats = interp->core_config.malloc_stats; /* Remaining threads (e.g. daemon threads) will automatically exit after taking the GIL (in PyEval_RestoreThread()). */ @@ -1205,7 +1153,7 @@ Py_FinalizeEx(void) _PyHash_Fini(); #ifdef Py_REF_DEBUG - if (core_config.show_ref_count) { + if (show_ref_count) { _PyDebug_PrintTotalRefs(); } #endif @@ -1216,7 +1164,7 @@ Py_FinalizeEx(void) * Alas, a lot of stuff may still be alive now that will be cleaned * up later. */ - if (core_config.dump_refs) { + if (dump_refs) { _Py_PrintReferences(stderr); } #endif /* Py_TRACE_REFS */ @@ -1280,12 +1228,12 @@ Py_FinalizeEx(void) * An address can be used to find the repr of the object, printed * above by _Py_PrintReferences. */ - if (core_config.dump_refs) { + if (dump_refs) { _Py_PrintReferenceAddresses(stderr); } #endif /* Py_TRACE_REFS */ #ifdef WITH_PYMALLOC - if (core_config.malloc_stats) { + if (malloc_stats) { _PyObject_DebugMallocStats(stderr); } #endif @@ -1347,14 +1295,23 @@ new_interpreter(PyThreadState **tstate_p) save_tstate = PyThreadState_Swap(tstate); /* Copy the current interpreter config into the new interpreter */ + _PyCoreConfig *core_config; + _PyMainInterpreterConfig *config; if (save_tstate != NULL) { - interp->core_config = save_tstate->interp->core_config; - interp->config = save_tstate->interp->config; + core_config = &save_tstate->interp->core_config; + config = &save_tstate->interp->config; } else { /* No current thread state, copy from the main interpreter */ PyInterpreterState *main_interp = PyInterpreterState_Main(); - interp->core_config = main_interp->core_config; - interp->config = main_interp->config; + core_config = &main_interp->core_config; + config = &main_interp->config; + } + + if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { + return _Py_INIT_ERR("failed to copy core config"); + } + if (_PyMainInterpreterConfig_Copy(&interp->config, config) < 0) { + return _Py_INIT_ERR("failed to copy main interpreter config"); } err = _PyPathConfig_Init(&interp->core_config); diff --git a/Python/pystate.c b/Python/pystate.c index 500f9676875..ec7eb450b66 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -183,6 +183,8 @@ PyInterpreterState_Clear(PyInterpreterState *interp) for (p = interp->tstate_head; p != NULL; p = p->next) PyThreadState_Clear(p); HEAD_UNLOCK(); + _PyCoreConfig_Clear(&interp->core_config); + _PyMainInterpreterConfig_Clear(&interp->config); Py_CLEAR(interp->codec_search_path); Py_CLEAR(interp->codec_search_cache); Py_CLEAR(interp->codec_error_registry); From webhook-mailer at python.org Thu Dec 14 20:05:33 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 01:05:33 -0000 Subject: [Python-checkins] bpo-32030: Add _PyMainInterpreterConfig.executable (#4876) Message-ID: https://github.com/python/cpython/commit/41264f1cd4d6066b2797ff07cae465c1e06ff3b2 commit: 41264f1cd4d6066b2797ff07cae465c1e06ff3b2 branch: master author: Victor Stinner committer: GitHub date: 2017-12-15T02:05:29+01:00 summary: bpo-32030: Add _PyMainInterpreterConfig.executable (#4876) * Add new fields to _PyMainInterpreterConfig: * executable * prefix * base_prefix * exec_prefix * base_exec_prefix * _PySys_EndInit() now sets sys attributes from _PyMainInterpreterConfig files: M Include/pylifecycle.h M Include/pystate.h M Modules/main.c M Python/pylifecycle.c M Python/sysmodule.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 39339da45af..dcb7fcb8495 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -135,7 +135,7 @@ PyAPI_FUNC(const char *) _Py_gitversion(void); #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void); PyAPI_FUNC(_PyInitError) _PySys_BeginInit(PyObject **sysmod); -PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict); +PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict, _PyMainInterpreterConfig *config); PyAPI_FUNC(_PyInitError) _PyImport_Init(PyInterpreterState *interp); PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod); PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void); diff --git a/Include/pystate.h b/Include/pystate.h index e8cf4134a8c..a56c9b4ea6c 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -52,15 +52,18 @@ typedef struct { /* Placeholders while working on the new configuration API * * See PEP 432 for final anticipated contents - * - * For the moment, just handle the args to _Py_InitializeEx */ typedef struct { int install_signal_handlers; - PyObject *argv; /* sys.argv list, can be NULL */ - PyObject *module_search_path; /* sys.path list */ - PyObject *warnoptions; /* sys.warnoptions list, can be NULL */ - PyObject *xoptions; /* sys._xoptions dict, can be NULL */ + PyObject *argv; /* sys.argv list, can be NULL */ + PyObject *executable; /* sys.executable str */ + PyObject *prefix; /* sys.prefix str */ + PyObject *base_prefix; /* sys.base_prefix str, can be NULL */ + PyObject *exec_prefix; /* sys.exec_prefix str */ + PyObject *base_exec_prefix; /* sys.base_exec_prefix str, can be NULL */ + PyObject *warnoptions; /* sys.warnoptions list, can be NULL */ + PyObject *xoptions; /* sys._xoptions dict, can be NULL */ + PyObject *module_search_path; /* sys.path list */ } _PyMainInterpreterConfig; #define _PyMainInterpreterConfig_INIT \ diff --git a/Modules/main.c b/Modules/main.c index 8c4219c7ec3..339a0f5e681 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -2005,9 +2005,14 @@ void _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) { Py_CLEAR(config->argv); - Py_CLEAR(config->module_search_path); + Py_CLEAR(config->executable); + Py_CLEAR(config->prefix); + Py_CLEAR(config->base_prefix); + Py_CLEAR(config->exec_prefix); + Py_CLEAR(config->base_exec_prefix); Py_CLEAR(config->warnoptions); Py_CLEAR(config->xoptions); + Py_CLEAR(config->module_search_path); } @@ -2052,9 +2057,14 @@ _PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config, } while (0) COPY_ATTR(argv); - COPY_ATTR(module_search_path); + COPY_ATTR(executable); + COPY_ATTR(prefix); + COPY_ATTR(base_prefix); + COPY_ATTR(exec_prefix); + COPY_ATTR(base_exec_prefix); COPY_ATTR(warnoptions); COPY_ATTR(xoptions); + COPY_ATTR(module_search_path); #undef COPY_ATTR return 0; } @@ -2099,26 +2109,14 @@ config_create_path_list(const wchar_t *path, wchar_t delim) } -static _PyInitError -config_init_module_search_path(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) +_PyInitError +_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) { _PyInitError err = _PyPathConfig_Init(core_config); if (_Py_INIT_FAILED(err)) { return err; } - wchar_t *sys_path = Py_GetPath(); - config->module_search_path = config_create_path_list(sys_path, DELIM); - if (config->module_search_path == NULL) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); -} - - -_PyInitError -_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) -{ /* Signal handlers are installed by default */ if (config->install_signal_handlers < 0) { config->install_signal_handlers = 1; @@ -2126,12 +2124,45 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *c if (config->module_search_path == NULL && !core_config->_disable_importlib) + { - _PyInitError err = config_init_module_search_path(config, core_config); - if (_Py_INIT_FAILED(err)) { - return err; + wchar_t *sys_path = Py_GetPath(); + config->module_search_path = config_create_path_list(sys_path, DELIM); + if (config->module_search_path == NULL) { + return _Py_INIT_NO_MEMORY(); } } + + if (config->executable == NULL) { + config->executable = PyUnicode_FromWideChar(Py_GetProgramFullPath(), -1); + if (config->executable == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + + if (config->prefix == NULL) { + config->prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1); + if (config->prefix == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + + if (config->exec_prefix == NULL) { + config->exec_prefix = PyUnicode_FromWideChar(Py_GetExecPrefix(), -1); + if (config->exec_prefix == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + + if (config->base_prefix == NULL) { + Py_INCREF(config->prefix); + config->base_prefix = config->prefix; + } + + if (config->base_exec_prefix == NULL) { + Py_INCREF(config->exec_prefix); + config->base_exec_prefix = config->exec_prefix; + } return _Py_INIT_OK(); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 830f89d0d41..8c626075d5d 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -830,28 +830,7 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return _Py_INIT_ERR("can't initialize time"); } - /* Set sys attributes */ - assert(interp->config.module_search_path != NULL); - if (PySys_SetObject("path", interp->config.module_search_path) != 0) { - return _Py_INIT_ERR("can't assign sys.path"); - } - if (interp->config.argv != NULL) { - if (PySys_SetObject("argv", interp->config.argv) != 0) { - return _Py_INIT_ERR("can't assign sys.argv"); - } - } - if (interp->config.warnoptions != NULL) { - if (PySys_SetObject("warnoptions", interp->config.warnoptions)) { - return _Py_INIT_ERR("can't assign sys.warnoptions"); - } - } - if (interp->config.xoptions != NULL) { - if (PySys_SetObject("_xoptions", interp->config.xoptions)) { - return _Py_INIT_ERR("can't assign sys._xoptions"); - } - } - - if (_PySys_EndInit(interp->sysdict) < 0) { + if (_PySys_EndInit(interp->sysdict, &interp->config) < 0) { return _Py_INIT_ERR("can't finish initializing sys"); } @@ -1314,12 +1293,6 @@ new_interpreter(PyThreadState **tstate_p) return _Py_INIT_ERR("failed to copy main interpreter config"); } - err = _PyPathConfig_Init(&interp->core_config); - if (_Py_INIT_FAILED(err)) { - return err; - } - wchar_t *sys_path = Py_GetPath(); - /* XXX The following is lax in error checking */ PyObject *modules = PyDict_New(); if (modules == NULL) { @@ -1334,8 +1307,7 @@ new_interpreter(PyThreadState **tstate_p) goto handle_error; Py_INCREF(interp->sysdict); PyDict_SetItemString(interp->sysdict, "modules", modules); - PySys_SetPath(sys_path); - _PySys_EndInit(interp->sysdict); + _PySys_EndInit(interp->sysdict, &interp->config); } bimod = _PyImport_FindBuiltin("builtins", modules); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index b33a316331a..24098b9daf8 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2212,7 +2212,6 @@ _PySys_BeginInit(PyObject **sysmod) } #undef SET_SYS_FROM_STRING -#undef SET_SYS_FROM_STRING_BORROW /* Updating the sys namespace, returning integer error codes */ #define SET_SYS_FROM_STRING_INT_RESULT(key, value) \ @@ -2228,10 +2227,35 @@ _PySys_BeginInit(PyObject **sysmod) } while (0) int -_PySys_EndInit(PyObject *sysdict) +_PySys_EndInit(PyObject *sysdict, _PyMainInterpreterConfig *config) { int res; + /* _PyMainInterpreterConfig_Read() must set all these variables */ + assert(config->module_search_path != NULL); + assert(config->executable != NULL); + assert(config->prefix != NULL); + assert(config->base_prefix != NULL); + assert(config->exec_prefix != NULL); + assert(config->base_exec_prefix != NULL); + + SET_SYS_FROM_STRING_BORROW("path", config->module_search_path); + SET_SYS_FROM_STRING_BORROW("executable", config->executable); + SET_SYS_FROM_STRING_BORROW("prefix", config->prefix); + SET_SYS_FROM_STRING_BORROW("base_prefix", config->base_prefix); + SET_SYS_FROM_STRING_BORROW("exec_prefix", config->exec_prefix); + SET_SYS_FROM_STRING_BORROW("base_exec_prefix", config->base_exec_prefix); + + if (config->argv != NULL) { + SET_SYS_FROM_STRING_BORROW("argv", config->argv); + } + if (config->warnoptions != NULL) { + SET_SYS_FROM_STRING_BORROW("warnoptions", config->warnoptions); + } + if (config->xoptions != NULL) { + SET_SYS_FROM_STRING_BORROW("_xoptions", config->xoptions); + } + /* Set flags to their final values */ SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags()); /* prevent user from creating new instances */ @@ -2247,17 +2271,6 @@ _PySys_EndInit(PyObject *sysdict) SET_SYS_FROM_STRING_INT_RESULT("dont_write_bytecode", PyBool_FromLong(Py_DontWriteBytecodeFlag)); - SET_SYS_FROM_STRING_INT_RESULT("executable", - PyUnicode_FromWideChar( - Py_GetProgramFullPath(), -1)); - SET_SYS_FROM_STRING_INT_RESULT("prefix", - PyUnicode_FromWideChar(Py_GetPrefix(), -1)); - SET_SYS_FROM_STRING_INT_RESULT("exec_prefix", - PyUnicode_FromWideChar(Py_GetExecPrefix(), -1)); - SET_SYS_FROM_STRING_INT_RESULT("base_prefix", - PyUnicode_FromWideChar(Py_GetPrefix(), -1)); - SET_SYS_FROM_STRING_INT_RESULT("base_exec_prefix", - PyUnicode_FromWideChar(Py_GetExecPrefix(), -1)); if (get_warnoptions() == NULL) return -1; @@ -2268,8 +2281,12 @@ _PySys_EndInit(PyObject *sysdict) if (PyErr_Occurred()) return -1; return 0; + +err_occurred: + return -1; } +#undef SET_SYS_FROM_STRING_BORROW #undef SET_SYS_FROM_STRING_INT_RESULT static PyObject * From lp_benchmark_robot at intel.com Thu Dec 14 20:06:27 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 14 Dec 2017 17:06:27 -0800 Subject: [Python-checkins] [2 up, 63 flat] Results for Python (master branch) 2017-12-14 Message-ID: <18c1d46b-fada-47a9-8371-4bfd4f4027c8@orsmsx107.amr.corp.intel.com> Results for project python/master, build date: 2017-12-14 03:03:29-08:00. - commit: 374c6e1 - previous commit: c3e070f - revision date: 2017-12-14 12:05:26+01:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.878% | +1.597% | +6.450% | +6.328% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 2.216% | -0.669% | +24.144% | +11.704% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.629% | +0.621% | +25.771% | +9.590% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.156% | +1.044% | +23.552% | +8.895% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.205% | +3.396% | +9.717% | +8.253% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.316% | -1.485% | +9.098% | +10.591% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.710% | +0.108% | +6.229% | +10.494% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.405% | +0.998% | +1.152% | +8.350% | +-----+------------------------+--------+------------+------------+------------+ | :-) | deltablue| 1.129% | +5.718% | +11.987% | +14.701% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.377% | +2.350% | +14.767% | +10.926% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.334% | +1.271% | +4.671% | +6.590% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.802% | +1.164% | +5.889% | +5.624% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.873% | +0.038% | +2.765% | +5.264% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 0.873% | +0.483% | +14.301% | +7.306% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 0.954% | +1.328% | +9.576% | +7.768% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 1.136% | +1.519% | +7.020% | +10.096% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 1.149% | -0.294% | +10.770% | +10.514% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.963% | -1.543% | +7.558% | +10.848% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.309% | +0.555% | +3.072% | +7.703% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 7.830% | +1.008% | -1.761% | +13.980% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.470% | +3.762% | +9.519% | +9.299% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.084% | -2.392% | +46.278% | +13.249% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.718% | +2.955% | +10.166% | +11.358% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.400% | +0.044% | +17.890% | +10.609% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 1.344% | -0.590% | +8.062% | +10.074% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 4.384% | +4.553% | +6.597% | +2.258% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.805% | -1.325% | +0.738% | -0.975% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.828% | +1.735% | +5.356% | +6.509% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.005% | -1.171% | +6.337% | +8.930% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.630% | +0.772% | +1.648% | +20.395% | +-----+------------------------+--------+------------+------------+------------+ | :-) | pickle_dict| 0.255% | +2.674% | +2.002% | +23.653% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.954% | -1.457% | +2.667% | +21.728% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.905% | -1.186% | +9.585% | +9.654% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.069% | +0.023% | +0.250% | +10.037% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.153% | -0.281% | +9.904% | +5.150% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.121% | -0.266% | +0.971% | +5.407% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.454% | +1.083% | +10.394% | +12.717% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.587% | +0.763% | +3.149% | +8.348% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.618% | +0.262% | -0.533% | +9.511% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.984% | +1.310% | -2.260% | +2.063% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.018% | -0.265% | +4.711% | +9.873% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 2.604% | -1.048% | +7.757% | +15.244% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.412% | +1.871% | -1.755% | +1.947% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 2.279% | +1.866% | +27.606% | +6.299% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.611% | -0.563% | +5.153% | +3.200% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.328% | +1.133% | +14.694% | +7.111% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.039% | +1.131% | -1.042% | -3.961% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.503% | -0.610% | +3.386% | +2.439% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.848% | +1.255% | +8.054% | +5.455% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.140% | +1.074% | +7.426% | +4.027% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 5.087% | +1.407% | +17.930% | +8.319% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.393% | +0.103% | +11.311% | +7.622% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.110% | -0.546% | +8.656% | +7.201% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 2.917% | +1.429% | +11.836% | +7.449% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 4.664% | +4.136% | +12.140% | +8.459% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.131% | +0.080% | +19.669% | +12.101% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.014% | +1.404% | +6.307% | +7.162% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.905% | -0.704% | +2.118% | +1.207% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 6.002% | +1.660% | +7.734% | +20.489% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.967% | +2.821% | -0.796% | +17.947% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.759% | +2.494% | +6.978% | +6.633% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.065% | -0.449% | +5.558% | +9.155% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.988% | +0.138% | +2.675% | +6.886% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.448% | +2.296% | -6.815% | +12.030% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.293% | -0.934% | +6.246% | +9.870% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/2-up-63-flat-results-for-python-master-branch-2017-12-14 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu Dec 14 20:53:29 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Fri, 15 Dec 2017 01:53:29 -0000 Subject: [Python-checkins] bpo-32327: Convert asyncio functions documented as coroutines to coroutines. (#4872) Message-ID: https://github.com/python/cpython/commit/19a44f63c738388ef3c8515348b4ffc061dfd627 commit: 19a44f63c738388ef3c8515348b4ffc061dfd627 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-14T20:53:26-05:00 summary: bpo-32327: Convert asyncio functions documented as coroutines to coroutines. (#4872) files: A Misc/NEWS.d/next/Library/2017-12-14-16-00-25.bpo-32327.bbkSxA.rst M Doc/library/asyncio-eventloop.rst M Lib/asyncio/base_events.py M Lib/asyncio/proactor_events.py M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_selector_events.py M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_asyncio/test_windows_events.py diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index c582b2779b0..26798783fe7 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -269,9 +269,8 @@ Creating connections socket type :py:data:`~socket.SOCK_STREAM`. *protocol_factory* must be a callable returning a :ref:`protocol ` instance. - This method is a :ref:`coroutine ` which will try to - establish the connection in the background. When successful, the - coroutine returns a ``(transport, protocol)`` pair. + This method will try to establish the connection in the background. + When successful, it returns a ``(transport, protocol)`` pair. The chronological synopsis of the underlying operation is as follows: @@ -344,9 +343,8 @@ Creating connections :py:data:`~socket.SOCK_DGRAM`. *protocol_factory* must be a callable returning a :ref:`protocol ` instance. - This method is a :ref:`coroutine ` which will try to - establish the connection in the background. When successful, the - coroutine returns a ``(transport, protocol)`` pair. + This method will try to establish the connection in the background. + When successful, the it returns a ``(transport, protocol)`` pair. Options changing how the connection is created: @@ -395,9 +393,8 @@ Creating connections family is used to communicate between processes on the same machine efficiently. - This method is a :ref:`coroutine ` which will try to - establish the connection in the background. When successful, the - coroutine returns a ``(transport, protocol)`` pair. + This method will try to establish the connection in the background. + When successful, the it returns a ``(transport, protocol)`` pair. *path* is the name of a UNIX domain socket, and is required unless a *sock* parameter is specified. Abstract UNIX sockets, :class:`str`, @@ -459,8 +456,6 @@ Creating listening connections set this flag when being created. This option is not supported on Windows. - This method is a :ref:`coroutine `. - .. versionchanged:: 3.5 On Windows with :class:`ProactorEventLoop`, SSL/TLS is now supported. @@ -484,8 +479,6 @@ Creating listening connections parameter is specified. Abstract UNIX sockets, :class:`str`, :class:`bytes`, and :class:`~pathlib.Path` paths are supported. - This method is a :ref:`coroutine `. - Availability: UNIX. .. versionchanged:: 3.7 @@ -507,8 +500,7 @@ Creating listening connections * *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over the accepted connections. - This method is a :ref:`coroutine `. When completed, the - coroutine returns a ``(transport, protocol)`` pair. + When completed it returns a ``(transport, protocol)`` pair. .. versionadded:: 3.5.3 @@ -565,7 +557,10 @@ Low-level socket operations With :class:`SelectorEventLoop` event loop, the socket *sock* must be non-blocking. - This method is a :ref:`coroutine `. + .. versionchanged:: 3.7 + Even though the method was always documented as a coroutine + method, before Python 3.7 it returned a :class:`Future`. + Since Python 3.7, this is an ``async def`` method. .. coroutinemethod:: AbstractEventLoop.sock_recv_into(sock, buf) @@ -578,8 +573,6 @@ Low-level socket operations With :class:`SelectorEventLoop` event loop, the socket *sock* must be non-blocking. - This method is a :ref:`coroutine `. - .. versionadded:: 3.7 .. coroutinemethod:: AbstractEventLoop.sock_sendall(sock, data) @@ -596,7 +589,10 @@ Low-level socket operations With :class:`SelectorEventLoop` event loop, the socket *sock* must be non-blocking. - This method is a :ref:`coroutine `. + .. versionchanged:: 3.7 + Even though the method was always documented as a coroutine + method, before Python 3.7 it returned an :class:`Future`. + Since Python 3.7, this is an ``async def`` method. .. coroutinemethod:: AbstractEventLoop.sock_connect(sock, address) @@ -606,8 +602,6 @@ Low-level socket operations With :class:`SelectorEventLoop` event loop, the socket *sock* must be non-blocking. - This method is a :ref:`coroutine `. - .. versionchanged:: 3.5.2 ``address`` no longer needs to be resolved. ``sock_connect`` will try to check if the *address* is already resolved by calling @@ -634,7 +628,10 @@ Low-level socket operations The socket *sock* must be non-blocking. - This method is a :ref:`coroutine `. + .. versionchanged:: 3.7 + Even though the method was always documented as a coroutine + method, before Python 3.7 it returned a :class:`Future`. + Since Python 3.7, this is an ``async def`` method. .. seealso:: @@ -673,8 +670,6 @@ Use :class:`ProactorEventLoop` to support pipes on Windows. With :class:`SelectorEventLoop` event loop, the *pipe* is set to non-blocking mode. - This method is a :ref:`coroutine `. - .. coroutinemethod:: AbstractEventLoop.connect_write_pipe(protocol_factory, pipe) Register write pipe in eventloop. @@ -687,8 +682,6 @@ Use :class:`ProactorEventLoop` to support pipes on Windows. With :class:`SelectorEventLoop` event loop, the *pipe* is set to non-blocking mode. - This method is a :ref:`coroutine `. - .. seealso:: The :meth:`AbstractEventLoop.subprocess_exec` and @@ -738,8 +731,6 @@ pool of processes). By default, an event loop uses a thread pool executor :ref:`Use functools.partial to pass keywords to the *func* `. - This method is a :ref:`coroutine `. - .. versionchanged:: 3.5.3 :meth:`BaseEventLoop.run_in_executor` no longer configures the ``max_workers`` of the thread pool executor it creates, instead @@ -747,6 +738,11 @@ pool of processes). By default, an event loop uses a thread pool executor (:class:`~concurrent.futures.ThreadPoolExecutor`) to set the default. + .. versionchanged:: 3.7 + Even though the method was always documented as a coroutine + method, before Python 3.7 it returned a :class:`Future`. + Since Python 3.7, this is an ``async def`` method. + .. method:: AbstractEventLoop.set_default_executor(executor) Set the default executor used by :meth:`run_in_executor`. @@ -857,8 +853,6 @@ Server Wait until the :meth:`close` method completes. - This method is a :ref:`coroutine `. - .. attribute:: sockets List of :class:`socket.socket` objects the server is listening to, or diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 9584d6355f8..80d2b693f1d 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -157,20 +157,6 @@ def _ipaddr_info(host, port, family, type, proto): return None -def _ensure_resolved(address, *, family=0, type=socket.SOCK_STREAM, proto=0, - flags=0, loop): - host, port = address[:2] - info = _ipaddr_info(host, port, family, type, proto) - if info is not None: - # "host" is already a resolved IP. - fut = loop.create_future() - fut.set_result([info]) - return fut - else: - return loop.getaddrinfo(host, port, family=family, type=type, - proto=proto, flags=flags) - - def _run_until_complete_cb(fut): exc = fut._exception if isinstance(exc, BaseException) and not isinstance(exc, Exception): @@ -614,7 +600,7 @@ def call_soon_threadsafe(self, callback, *args): self._write_to_self() return handle - def run_in_executor(self, executor, func, *args): + async def run_in_executor(self, executor, func, *args): self._check_closed() if self._debug: self._check_callback(func, 'run_in_executor') @@ -623,7 +609,8 @@ def run_in_executor(self, executor, func, *args): if executor is None: executor = concurrent.futures.ThreadPoolExecutor() self._default_executor = executor - return futures.wrap_future(executor.submit(func, *args), loop=self) + return await futures.wrap_future( + executor.submit(func, *args), loop=self) def set_default_executor(self, executor): self._default_executor = executor @@ -652,17 +639,19 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): logger.debug(msg) return addrinfo - def getaddrinfo(self, host, port, *, - family=0, type=0, proto=0, flags=0): + async def getaddrinfo(self, host, port, *, + family=0, type=0, proto=0, flags=0): if self._debug: - return self.run_in_executor(None, self._getaddrinfo_debug, - host, port, family, type, proto, flags) + getaddr_func = self._getaddrinfo_debug else: - return self.run_in_executor(None, socket.getaddrinfo, - host, port, family, type, proto, flags) + getaddr_func = socket.getaddrinfo - def getnameinfo(self, sockaddr, flags=0): - return self.run_in_executor(None, socket.getnameinfo, sockaddr, flags) + return await self.run_in_executor( + None, getaddr_func, host, port, family, type, proto, flags) + + async def getnameinfo(self, sockaddr, flags=0): + return await self.run_in_executor( + None, socket.getnameinfo, sockaddr, flags) async def create_connection(self, protocol_factory, host=None, port=None, *, ssl=None, family=0, @@ -703,25 +692,17 @@ def getnameinfo(self, sockaddr, flags=0): raise ValueError( 'host/port and sock can not be specified at the same time') - f1 = _ensure_resolved((host, port), family=family, - type=socket.SOCK_STREAM, proto=proto, - flags=flags, loop=self) - fs = [f1] - if local_addr is not None: - f2 = _ensure_resolved(local_addr, family=family, - type=socket.SOCK_STREAM, proto=proto, - flags=flags, loop=self) - fs.append(f2) - else: - f2 = None - - await tasks.wait(fs, loop=self) - - infos = f1.result() + infos = await self._ensure_resolved( + (host, port), family=family, + type=socket.SOCK_STREAM, proto=proto, flags=flags, loop=self) if not infos: raise OSError('getaddrinfo() returned empty list') - if f2 is not None: - laddr_infos = f2.result() + + if local_addr is not None: + laddr_infos = await self._ensure_resolved( + local_addr, family=family, + type=socket.SOCK_STREAM, proto=proto, + flags=flags, loop=self) if not laddr_infos: raise OSError('getaddrinfo() returned empty list') @@ -730,7 +711,7 @@ def getnameinfo(self, sockaddr, flags=0): try: sock = socket.socket(family=family, type=type, proto=proto) sock.setblocking(False) - if f2 is not None: + if local_addr is not None: for _, _, _, _, laddr in laddr_infos: try: sock.bind(laddr) @@ -863,7 +844,7 @@ def getnameinfo(self, sockaddr, flags=0): assert isinstance(addr, tuple) and len(addr) == 2, ( '2-tuple is expected') - infos = await _ensure_resolved( + infos = await self._ensure_resolved( addr, family=family, type=socket.SOCK_DGRAM, proto=proto, flags=flags, loop=self) if not infos: @@ -946,10 +927,22 @@ def getnameinfo(self, sockaddr, flags=0): return transport, protocol + async def _ensure_resolved(self, address, *, + family=0, type=socket.SOCK_STREAM, + proto=0, flags=0, loop): + host, port = address[:2] + info = _ipaddr_info(host, port, family, type, proto) + if info is not None: + # "host" is already a resolved IP. + return [info] + else: + return await loop.getaddrinfo(host, port, family=family, type=type, + proto=proto, flags=flags) + async def _create_server_getaddrinfo(self, host, port, family, flags): - infos = await _ensure_resolved((host, port), family=family, - type=socket.SOCK_STREAM, - flags=flags, loop=self) + infos = await self._ensure_resolved((host, port), family=family, + type=socket.SOCK_STREAM, + flags=flags, loop=self) if not infos: raise OSError(f'getaddrinfo({host!r}) returned empty list') return infos diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 3d48a2c05a2..291d989cc45 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -432,20 +432,20 @@ def close(self): # Close the event loop super().close() - def sock_recv(self, sock, n): - return self._proactor.recv(sock, n) + async def sock_recv(self, sock, n): + return await self._proactor.recv(sock, n) - def sock_recv_into(self, sock, buf): - return self._proactor.recv_into(sock, buf) + async def sock_recv_into(self, sock, buf): + return await self._proactor.recv_into(sock, buf) - def sock_sendall(self, sock, data): - return self._proactor.send(sock, data) + async def sock_sendall(self, sock, data): + return await self._proactor.send(sock, data) - def sock_connect(self, sock, address): - return self._proactor.connect(sock, address) + async def sock_connect(self, sock, address): + return await self._proactor.connect(sock, address) - def sock_accept(self, sock): - return self._proactor.accept(sock) + async def sock_accept(self, sock): + return await self._proactor.accept(sock) def _close_self_pipe(self): if self._self_reading_future is not None: diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 2467e23e854..78ebf3e5fca 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -336,20 +336,18 @@ def remove_writer(self, fd): self._ensure_fd_no_transport(fd) return self._remove_writer(fd) - def sock_recv(self, sock, n): + async def sock_recv(self, sock, n): """Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by nbytes. - - This method is a coroutine. """ if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") fut = self.create_future() self._sock_recv(fut, None, sock, n) - return fut + return await fut def _sock_recv(self, fut, registered_fd, sock, n): # _sock_recv() can add itself as an I/O callback if the operation can't @@ -372,19 +370,17 @@ def _sock_recv(self, fut, registered_fd, sock, n): else: fut.set_result(data) - def sock_recv_into(self, sock, buf): + async def sock_recv_into(self, sock, buf): """Receive data from the socket. The received data is written into *buf* (a writable buffer). The return value is the number of bytes written. - - This method is a coroutine. """ if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") fut = self.create_future() self._sock_recv_into(fut, None, sock, buf) - return fut + return await fut def _sock_recv_into(self, fut, registered_fd, sock, buf): # _sock_recv_into() can add itself as an I/O callback if the operation @@ -408,7 +404,7 @@ def _sock_recv_into(self, fut, registered_fd, sock, buf): else: fut.set_result(nbytes) - def sock_sendall(self, sock, data): + async def sock_sendall(self, sock, data): """Send data to the socket. The socket must be connected to a remote socket. This method continues @@ -416,8 +412,6 @@ def sock_sendall(self, sock, data): error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully processed by the receiving end of the connection. - - This method is a coroutine. """ if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") @@ -426,7 +420,7 @@ def sock_sendall(self, sock, data): self._sock_sendall(fut, None, sock, data) else: fut.set_result(None) - return fut + return await fut def _sock_sendall(self, fut, registered_fd, sock, data): if registered_fd is not None: @@ -459,11 +453,9 @@ def _sock_sendall(self, fut, registered_fd, sock, data): raise ValueError("the socket must be non-blocking") if not hasattr(socket, 'AF_UNIX') or sock.family != socket.AF_UNIX: - resolved = base_events._ensure_resolved( + resolved = await self._ensure_resolved( address, family=sock.family, proto=sock.proto, loop=self) - if not resolved.done(): - await resolved - _, _, _, _, address = resolved.result()[0] + _, _, _, _, address = resolved[0] fut = self.create_future() self._sock_connect(fut, sock, address) @@ -506,21 +498,19 @@ def _sock_connect_cb(self, fut, sock, address): else: fut.set_result(None) - def sock_accept(self, sock): + async def sock_accept(self, sock): """Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection. - - This method is a coroutine. """ if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") fut = self.create_future() self._sock_accept(fut, False, sock) - return fut + return await fut def _sock_accept(self, fut, registered, sock): fd = sock.fileno() diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index e43fe6948af..f8427cd5a86 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -217,14 +217,6 @@ def test_set_default_executor(self): self.loop.set_default_executor(executor) self.assertIs(executor, self.loop._default_executor) - def test_getnameinfo(self): - sockaddr = mock.Mock() - self.loop.run_in_executor = mock.Mock() - self.loop.getnameinfo(sockaddr) - self.assertEqual( - (None, socket.getnameinfo, sockaddr, 0), - self.loop.run_in_executor.call_args[0]) - def test_call_soon(self): def cb(): pass @@ -345,26 +337,6 @@ def test_thread(loop, debug, create_loop=False): # check disabled if debug mode is disabled test_thread(self.loop, False, create_loop=True) - def test_run_once_in_executor_plain(self): - def cb(): - pass - f = asyncio.Future(loop=self.loop) - executor = mock.Mock() - executor.submit.return_value = f - - self.loop.set_default_executor(executor) - - res = self.loop.run_in_executor(None, cb) - self.assertIs(f, res) - - executor = mock.Mock() - executor.submit.return_value = f - res = self.loop.run_in_executor(executor, cb) - self.assertIs(f, res) - self.assertTrue(executor.submit.called) - - f.cancel() # Don't complain about abandoned Future. - def test__run_once(self): h1 = asyncio.TimerHandle(time.monotonic() + 5.0, lambda: True, (), self.loop) @@ -1007,6 +979,12 @@ def setUp(self): self.loop = asyncio.new_event_loop() self.set_event_loop(self.loop) + @mock.patch('socket.getnameinfo') + def test_getnameinfo(self, m_gai): + m_gai.side_effect = lambda *args: 42 + r = self.loop.run_until_complete(self.loop.getnameinfo(('abc', 123))) + self.assertEqual(r, 42) + @patch_socket def test_create_connection_multiple_errors(self, m_socket): @@ -1119,9 +1097,7 @@ def getaddrinfo_task(*args, **kwds): OSError, self.loop.run_until_complete, coro) def test_create_connection_connect_err(self): - @asyncio.coroutine - def getaddrinfo(*args, **kw): - yield from [] + async def getaddrinfo(*args, **kw): return [(2, 1, 6, '', ('107.6.106.82', 80))] def getaddrinfo_task(*args, **kwds): @@ -1714,10 +1690,11 @@ def test_accept_connection_exception(self, m_log): self.assertTrue(m_log.error.called) self.assertFalse(sock.close.called) self.loop._remove_reader.assert_called_with(10) - self.loop.call_later.assert_called_with(constants.ACCEPT_RETRY_DELAY, - # self.loop._start_serving - mock.ANY, - MyProto, sock, None, None, mock.ANY) + self.loop.call_later.assert_called_with( + constants.ACCEPT_RETRY_DELAY, + # self.loop._start_serving + mock.ANY, + MyProto, sock, None, None, mock.ANY) def test_call_coroutine(self): @asyncio.coroutine @@ -1738,7 +1715,8 @@ def simple_coroutine(): with self.assertRaises(TypeError): self.loop.call_at(self.loop.time() + 60, func) with self.assertRaises(TypeError): - self.loop.run_in_executor(None, func) + self.loop.run_until_complete( + self.loop.run_in_executor(None, func)) @mock.patch('asyncio.base_events.logger') def test_log_slow_callbacks(self, m_logger): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 45a8bb86f63..58e94d46da8 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1702,7 +1702,7 @@ def reader(data): def test_prompt_cancellation(self): r, w = socket.socketpair() r.setblocking(False) - f = self.loop.sock_recv(r, 1) + f = self.loop.create_task(self.loop.sock_recv(r, 1)) ov = getattr(f, 'ov', None) if ov is not None: self.assertTrue(ov.pending) @@ -1819,7 +1819,8 @@ def test(): with self.assertRaises(RuntimeError): self.loop.call_at(self.loop.time() + .0, func) with self.assertRaises(RuntimeError): - self.loop.run_in_executor(None, func) + self.loop.run_until_complete( + self.loop.run_in_executor(None, func)) with self.assertRaises(RuntimeError): self.loop.create_task(coro) with self.assertRaises(RuntimeError): diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index c3bac95c862..910f2596620 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -483,27 +483,6 @@ def test_close(self): self.loop.close() self.assertFalse(self.loop._close_self_pipe.called) - def test_sock_recv(self): - self.loop.sock_recv(self.sock, 1024) - self.proactor.recv.assert_called_with(self.sock, 1024) - - def test_sock_recv_into(self): - buf = bytearray(10) - self.loop.sock_recv_into(self.sock, buf) - self.proactor.recv_into.assert_called_with(self.sock, buf) - - def test_sock_sendall(self): - self.loop.sock_sendall(self.sock, b'data') - self.proactor.send.assert_called_with(self.sock, b'data') - - def test_sock_connect(self): - self.loop.sock_connect(self.sock, ('1.2.3.4', 123)) - self.proactor.connect.assert_called_with(self.sock, ('1.2.3.4', 123)) - - def test_sock_accept(self): - self.loop.sock_accept(self.sock) - self.proactor.accept.assert_called_with(self.sock) - def test_make_socket_transport(self): tr = self.loop._make_socket_transport(self.sock, asyncio.Protocol()) self.assertIsInstance(tr, _ProactorSocketTransport) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 24feb30e3d5..04b0f97b2ab 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -176,9 +176,15 @@ def test_sock_recv(self): sock = test_utils.mock_nonblocking_socket() self.loop._sock_recv = mock.Mock() - f = self.loop.sock_recv(sock, 1024) - self.assertIsInstance(f, asyncio.Future) - self.loop._sock_recv.assert_called_with(f, None, sock, 1024) + f = self.loop.create_task(self.loop.sock_recv(sock, 1024)) + self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) + + self.assertEqual(self.loop._sock_recv.call_args[0][1:], + (None, sock, 1024)) + + f.cancel() + with self.assertRaises(asyncio.CancelledError): + self.loop.run_until_complete(f) def test_sock_recv_reconnection(self): sock = mock.Mock() @@ -188,7 +194,11 @@ def test_sock_recv_reconnection(self): self.loop.add_reader = mock.Mock() self.loop.remove_reader = mock.Mock() - fut = self.loop.sock_recv(sock, 1024) + fut = self.loop.create_task( + self.loop.sock_recv(sock, 1024)) + + self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) + callback = self.loop.add_reader.call_args[0][1] params = self.loop.add_reader.call_args[0][2:] @@ -198,6 +208,8 @@ def test_sock_recv_reconnection(self): sock.recv.side_effect = OSError(9) callback(*params) + self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) + self.assertIsInstance(fut.exception(), OSError) self.assertEqual((10,), self.loop.remove_reader.call_args[0]) @@ -245,18 +257,26 @@ def test_sock_sendall(self): sock = test_utils.mock_nonblocking_socket() self.loop._sock_sendall = mock.Mock() - f = self.loop.sock_sendall(sock, b'data') - self.assertIsInstance(f, asyncio.Future) + f = self.loop.create_task( + self.loop.sock_sendall(sock, b'data')) + + self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) + self.assertEqual( - (f, None, sock, b'data'), - self.loop._sock_sendall.call_args[0]) + (None, sock, b'data'), + self.loop._sock_sendall.call_args[0][1:]) + + f.cancel() + with self.assertRaises(asyncio.CancelledError): + self.loop.run_until_complete(f) def test_sock_sendall_nodata(self): sock = test_utils.mock_nonblocking_socket() self.loop._sock_sendall = mock.Mock() - f = self.loop.sock_sendall(sock, b'') - self.assertIsInstance(f, asyncio.Future) + f = self.loop.create_task(self.loop.sock_sendall(sock, b'')) + self.loop.run_until_complete(asyncio.sleep(0, loop=self.loop)) + self.assertTrue(f.done()) self.assertIsNone(f.result()) self.assertFalse(self.loop._sock_sendall.called) @@ -269,7 +289,10 @@ def test_sock_sendall_reconnection(self): self.loop.add_writer = mock.Mock() self.loop.remove_writer = mock.Mock() - fut = self.loop.sock_sendall(sock, b'data') + fut = self.loop.create_task(self.loop.sock_sendall(sock, b'data')) + + self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) + callback = self.loop.add_writer.call_args[0][1] params = self.loop.add_writer.call_args[0][2:] @@ -279,6 +302,8 @@ def test_sock_sendall_reconnection(self): sock.send.side_effect = OSError(9) callback(*params) + self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) + self.assertIsInstance(fut.exception(), OSError) self.assertEqual((10,), self.loop.remove_writer.call_args[0]) @@ -402,17 +427,17 @@ def test_sock_connect_timeout(self): def test_sock_connect_resolve_using_socket_params(self, m_gai): addr = ('need-resolution.com', 8080) sock = test_utils.mock_nonblocking_socket() - m_gai.side_effect = (None, None, None, None, ('127.0.0.1', 0)) - m_gai._is_coroutine = False + + m_gai.side_effect = \ + lambda *args: [(None, None, None, None, ('127.0.0.1', 0))] + con = self.loop.create_task(self.loop.sock_connect(sock, addr)) - while not m_gai.called: - self.loop._run_once() + self.loop.run_until_complete(con) m_gai.assert_called_with( addr[0], addr[1], sock.family, sock.type, sock.proto, 0) - con.cancel() - with self.assertRaises(asyncio.CancelledError): - self.loop.run_until_complete(con) + self.loop.run_until_complete(con) + sock.connect.assert_called_with(('127.0.0.1', 0)) def test__sock_connect(self): f = asyncio.Future(loop=self.loop) @@ -487,10 +512,15 @@ def test_sock_accept(self): sock = test_utils.mock_nonblocking_socket() self.loop._sock_accept = mock.Mock() - f = self.loop.sock_accept(sock) - self.assertIsInstance(f, asyncio.Future) - self.assertEqual( - (f, False, sock), self.loop._sock_accept.call_args[0]) + f = self.loop.create_task(self.loop.sock_accept(sock)) + self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) + + self.assertFalse(self.loop._sock_accept.call_args[0][1]) + self.assertIs(self.loop._sock_accept.call_args[0][2], sock) + + f.cancel() + with self.assertRaises(asyncio.CancelledError): + self.loop.run_until_complete(f) def test__sock_accept(self): f = asyncio.Future(loop=self.loop) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 0838ebf3a7b..a5563ba9c6c 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2545,19 +2545,26 @@ def test_run_coroutine_threadsafe_task_cancelled(self): def test_run_coroutine_threadsafe_task_factory_exception(self): """Test coroutine submission from a tread to an event loop when the task factory raise an exception.""" - # Schedule the target - future = self.loop.run_in_executor( - None, lambda: self.target(advance_coro=True)) - # Set corrupted task factory - self.loop.set_task_factory(lambda loop, coro: wrong_name) + + def task_factory(loop, coro): + raise NameError + + run = self.loop.create_task( + self.loop.run_in_executor( + None, lambda: self.target(advance_coro=True))) + # Set exception handler callback = test_utils.MockCallback() self.loop.set_exception_handler(callback) + + # Set corrupted task factory + self.loop.set_task_factory(task_factory) + # Run event loop with self.assertRaises(NameError) as exc_context: - self.loop.run_until_complete(future) + self.loop.run_until_complete(run) + # Check exceptions - self.assertIn('wrong_name', exc_context.exception.args[0]) self.assertEqual(len(callback.call_args_list), 1) (loop, context), kwargs = callback.call_args self.assertEqual(context['exception'], exc_context.exception) diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index fdba636f207..e4ff7fc7dd4 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -39,7 +39,7 @@ def setUp(self): def test_close(self): a, b = socket.socketpair() trans = self.loop._make_socket_transport(a, asyncio.Protocol()) - f = asyncio.ensure_future(self.loop.sock_recv(b, 100)) + f = asyncio.ensure_future(self.loop.sock_recv(b, 100), loop=self.loop) trans.close() self.loop.run_until_complete(f) self.assertEqual(f.result(), b'') diff --git a/Misc/NEWS.d/next/Library/2017-12-14-16-00-25.bpo-32327.bbkSxA.rst b/Misc/NEWS.d/next/Library/2017-12-14-16-00-25.bpo-32327.bbkSxA.rst new file mode 100644 index 00000000000..5fd9fbca4b4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-14-16-00-25.bpo-32327.bbkSxA.rst @@ -0,0 +1,3 @@ +Convert asyncio functions that were documented as coroutines to coroutines. +Affected functions: loop.sock_sendall, loop.sock_recv, loop.sock_accept, +loop.run_in_executor, loop.getaddrinfo, loop.getnameinfo. From webhook-mailer at python.org Fri Dec 15 00:04:45 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Fri, 15 Dec 2017 05:04:45 -0000 Subject: [Python-checkins] bpo-32311: Implement asyncio.create_task() shortcut (#4848) Message-ID: https://github.com/python/cpython/commit/f74ef458ab1f502e4e60bd1502ac1dc0d2cb3847 commit: f74ef458ab1f502e4e60bd1502ac1dc0d2cb3847 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-15T07:04:38+02:00 summary: bpo-32311: Implement asyncio.create_task() shortcut (#4848) * Implement functionality * Add documentation files: A Lib/asyncio/format_helpers.py A Misc/NEWS.d/next/Library/2017-12-14-17-28-54.bpo-32311.DL5Ytn.rst M Doc/library/asyncio-task.rst M Lib/asyncio/base_futures.py M Lib/asyncio/constants.py M Lib/asyncio/coroutines.py M Lib/asyncio/events.py M Lib/asyncio/futures.py M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_asyncio/utils.py M Modules/_asynciomodule.c diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 0d0569f0ba1..72fae5e8559 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -371,10 +371,21 @@ with the result. Task ---- +.. function:: create_task(coro) + + Wrap a :ref:`coroutine ` *coro* into a task and schedule + its execution. Return the task object. + + The task is executed in :func:`get_running_loop` context, + :exc:`RuntimeError` is raised if there is no running loop in + current thread. + + .. versionadded:: 3.7 + .. class:: Task(coro, \*, loop=None) - Schedule the execution of a :ref:`coroutine `: wrap it in a - future. A task is a subclass of :class:`Future`. + A unit for concurrent running of :ref:`coroutines `, + subclass of :class:`Future`. A task is responsible for executing a coroutine object in an event loop. If the wrapped coroutine yields from a future, the task suspends the execution @@ -399,7 +410,7 @@ Task ` did not complete. It is probably a bug and a warning is logged: see :ref:`Pending task destroyed `. - Don't directly create :class:`Task` instances: use the :func:`ensure_future` + Don't directly create :class:`Task` instances: use the :func:`create_task` function or the :meth:`AbstractEventLoop.create_task` method. This class is :ref:`not thread safe `. @@ -547,9 +558,15 @@ Task functions .. versionchanged:: 3.5.1 The function accepts any :term:`awaitable` object. + .. note:: + + :func:`create_task` (added in Python 3.7) is the preferable way + for spawning new tasks. + .. seealso:: - The :meth:`AbstractEventLoop.create_task` method. + The :func:`create_task` function and + :meth:`AbstractEventLoop.create_task` method. .. function:: wrap_future(future, \*, loop=None) diff --git a/Lib/asyncio/base_futures.py b/Lib/asyncio/base_futures.py index 2ee82c3f057..008812eda91 100644 --- a/Lib/asyncio/base_futures.py +++ b/Lib/asyncio/base_futures.py @@ -3,7 +3,7 @@ import concurrent.futures._base import reprlib -from . import events +from . import format_helpers Error = concurrent.futures._base.Error CancelledError = concurrent.futures.CancelledError @@ -38,7 +38,7 @@ def _format_callbacks(cb): cb = '' def format_cb(callback): - return events._format_callback_source(callback, ()) + return format_helpers._format_callback_source(callback, ()) if size == 1: cb = format_cb(cb[0]) diff --git a/Lib/asyncio/constants.py b/Lib/asyncio/constants.py index dfe97f49859..52169c3f8e5 100644 --- a/Lib/asyncio/constants.py +++ b/Lib/asyncio/constants.py @@ -6,5 +6,5 @@ # Number of stack entries to capture in debug mode. # The larger the number, the slower the operation in debug mode -# (see extract_stack() in events.py). +# (see extract_stack() in format_helpers.py). DEBUG_STACK_DEPTH = 10 diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index bca7fe3a537..e3c0162dd14 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -9,9 +9,9 @@ from collections.abc import Awaitable, Coroutine -from . import constants -from . import events from . import base_futures +from . import constants +from . import format_helpers from .log import logger @@ -48,7 +48,7 @@ def __init__(self, gen, func=None): assert inspect.isgenerator(gen) or inspect.iscoroutine(gen), gen self.gen = gen self.func = func # Used to unwrap @coroutine decorator - self._source_traceback = events.extract_stack(sys._getframe(1)) + self._source_traceback = format_helpers.extract_stack(sys._getframe(1)) self.__name__ = getattr(gen, '__name__', None) self.__qualname__ = getattr(gen, '__qualname__', None) @@ -243,7 +243,7 @@ def _format_coroutine(coro): func = coro if coro_name is None: - coro_name = events._format_callback(func, (), {}) + coro_name = format_helpers._format_callback(func, (), {}) try: coro_code = coro.gi_code @@ -260,7 +260,7 @@ def _format_coroutine(coro): if (isinstance(coro, CoroWrapper) and not inspect.isgeneratorfunction(coro.func) and coro.func is not None): - source = events._get_function_source(coro.func) + source = format_helpers._get_function_source(coro.func) if source is not None: filename, lineno = source if coro_frame is None: diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index a00f861a9e5..974a4a22218 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -11,86 +11,14 @@ '_get_running_loop', ) -import functools -import inspect import os -import reprlib import socket import subprocess import sys import threading -import traceback from . import constants - - -def _get_function_source(func): - func = inspect.unwrap(func) - if inspect.isfunction(func): - code = func.__code__ - return (code.co_filename, code.co_firstlineno) - if isinstance(func, functools.partial): - return _get_function_source(func.func) - if isinstance(func, functools.partialmethod): - return _get_function_source(func.func) - return None - - -def _format_args_and_kwargs(args, kwargs): - """Format function arguments and keyword arguments. - - Special case for a single parameter: ('hello',) is formatted as ('hello'). - """ - # use reprlib to limit the length of the output - items = [] - if args: - items.extend(reprlib.repr(arg) for arg in args) - if kwargs: - items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items()) - return '({})'.format(', '.join(items)) - - -def _format_callback(func, args, kwargs, suffix=''): - if isinstance(func, functools.partial): - suffix = _format_args_and_kwargs(args, kwargs) + suffix - return _format_callback(func.func, func.args, func.keywords, suffix) - - if hasattr(func, '__qualname__'): - func_repr = getattr(func, '__qualname__') - elif hasattr(func, '__name__'): - func_repr = getattr(func, '__name__') - else: - func_repr = repr(func) - - func_repr += _format_args_and_kwargs(args, kwargs) - if suffix: - func_repr += suffix - return func_repr - - -def _format_callback_source(func, args): - func_repr = _format_callback(func, args, None) - source = _get_function_source(func) - if source: - func_repr += f' at {source[0]}:{source[1]}' - return func_repr - - -def extract_stack(f=None, limit=None): - """Replacement for traceback.extract_stack() that only does the - necessary work for asyncio debug mode. - """ - if f is None: - f = sys._getframe().f_back - if limit is None: - # Limit the amount of work to a reasonable amount, as extract_stack() - # can be called for each coroutine and future in debug mode. - limit = constants.DEBUG_STACK_DEPTH - stack = traceback.StackSummary.extract(traceback.walk_stack(f), - limit=limit, - lookup_lines=False) - stack.reverse() - return stack +from . import format_helpers class Handle: @@ -106,7 +34,8 @@ def __init__(self, callback, args, loop): self._cancelled = False self._repr = None if self._loop.get_debug(): - self._source_traceback = extract_stack(sys._getframe(1)) + self._source_traceback = format_helpers.extract_stack( + sys._getframe(1)) else: self._source_traceback = None @@ -115,7 +44,8 @@ def _repr_info(self): if self._cancelled: info.append('cancelled') if self._callback is not None: - info.append(_format_callback_source(self._callback, self._args)) + info.append(format_helpers._format_callback_source( + self._callback, self._args)) if self._source_traceback: frame = self._source_traceback[-1] info.append(f'created at {frame[0]}:{frame[1]}') @@ -145,7 +75,8 @@ def _run(self): try: self._callback(*self._args) except Exception as exc: - cb = _format_callback_source(self._callback, self._args) + cb = format_helpers._format_callback_source( + self._callback, self._args) msg = f'Exception in callback {cb}' context = { 'message': msg, diff --git a/Lib/asyncio/format_helpers.py b/Lib/asyncio/format_helpers.py new file mode 100644 index 00000000000..39cfcee0c1c --- /dev/null +++ b/Lib/asyncio/format_helpers.py @@ -0,0 +1,75 @@ +import functools +import inspect +import reprlib +import traceback + +from . import constants + + +def _get_function_source(func): + func = inspect.unwrap(func) + if inspect.isfunction(func): + code = func.__code__ + return (code.co_filename, code.co_firstlineno) + if isinstance(func, functools.partial): + return _get_function_source(func.func) + if isinstance(func, functools.partialmethod): + return _get_function_source(func.func) + return None + + +def _format_callback_source(func, args): + func_repr = _format_callback(func, args, None) + source = _get_function_source(func) + if source: + func_repr += f' at {source[0]}:{source[1]}' + return func_repr + + +def _format_args_and_kwargs(args, kwargs): + """Format function arguments and keyword arguments. + + Special case for a single parameter: ('hello',) is formatted as ('hello'). + """ + # use reprlib to limit the length of the output + items = [] + if args: + items.extend(reprlib.repr(arg) for arg in args) + if kwargs: + items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items()) + return '({})'.format(', '.join(items)) + + +def _format_callback(func, args, kwargs, suffix=''): + if isinstance(func, functools.partial): + suffix = _format_args_and_kwargs(args, kwargs) + suffix + return _format_callback(func.func, func.args, func.keywords, suffix) + + if hasattr(func, '__qualname__'): + func_repr = getattr(func, '__qualname__') + elif hasattr(func, '__name__'): + func_repr = getattr(func, '__name__') + else: + func_repr = repr(func) + + func_repr += _format_args_and_kwargs(args, kwargs) + if suffix: + func_repr += suffix + return func_repr + + +def extract_stack(f=None, limit=None): + """Replacement for traceback.extract_stack() that only does the + necessary work for asyncio debug mode. + """ + if f is None: + f = sys._getframe().f_back + if limit is None: + # Limit the amount of work to a reasonable amount, as extract_stack() + # can be called for each coroutine and future in debug mode. + limit = constants.DEBUG_STACK_DEPTH + stack = traceback.StackSummary.extract(traceback.walk_stack(f), + limit=limit, + lookup_lines=False) + stack.reverse() + return stack diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index d46a295197b..b310962f9fe 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -11,6 +11,7 @@ from . import base_futures from . import events +from . import format_helpers CancelledError = base_futures.CancelledError @@ -79,7 +80,8 @@ def __init__(self, *, loop=None): self._loop = loop self._callbacks = [] if self._loop.get_debug(): - self._source_traceback = events.extract_stack(sys._getframe(1)) + self._source_traceback = format_helpers.extract_stack( + sys._getframe(1)) _repr_info = base_futures._future_repr_info diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index c5122f76071..172057e5a29 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -1,7 +1,7 @@ """Support for tasks, coroutines and the scheduler.""" __all__ = ( - 'Task', + 'Task', 'create_task', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', 'wait', 'wait_for', 'as_completed', 'sleep', 'gather', 'shield', 'ensure_future', 'run_coroutine_threadsafe', @@ -67,13 +67,19 @@ def all_tasks(cls, loop=None): return {t for t in cls._all_tasks if t._loop is loop} def __init__(self, coro, *, loop=None): - assert coroutines.iscoroutine(coro), repr(coro) super().__init__(loop=loop) if self._source_traceback: del self._source_traceback[-1] - self._coro = coro - self._fut_waiter = None + if not coroutines.iscoroutine(coro): + # raise after Future.__init__(), attrs are required for __del__ + # prevent logging for pending task in __del__ + self._log_destroy_pending = False + raise TypeError(f"a coroutine was expected, got {coro!r}") + self._must_cancel = False + self._fut_waiter = None + self._coro = coro + self._loop.call_soon(self._step) self.__class__._all_tasks.add(self) @@ -263,6 +269,15 @@ def _wakeup(self, future): Task = _CTask = _asyncio.Task +def create_task(coro): + """Schedule the execution of a coroutine object in a spawn task. + + Return a Task object. + """ + loop = events.get_running_loop() + return loop.create_task(coro) + + # wait() and as_completed() similar to those in PEP 3148. FIRST_COMPLETED = concurrent.futures.FIRST_COMPLETED diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index a5563ba9c6c..a32dca13118 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2054,6 +2054,43 @@ def coro(): self.assertEqual(self.Task.all_tasks(self.loop), set()) + def test_create_task_with_noncoroutine(self): + with self.assertRaisesRegex(TypeError, + "a coroutine was expected, got 123"): + self.new_task(self.loop, 123) + + def test_create_task_with_oldstyle_coroutine(self): + + @asyncio.coroutine + def coro(): + pass + + task = self.new_task(self.loop, coro()) + self.assertIsInstance(task, self.Task) + self.loop.run_until_complete(task) + + def test_create_task_with_async_function(self): + + async def coro(): + pass + + task = self.new_task(self.loop, coro()) + self.assertIsInstance(task, self.Task) + self.loop.run_until_complete(task) + + def test_bare_create_task(self): + + async def inner(): + return 1 + + async def coro(): + task = asyncio.create_task(inner()) + self.assertIsInstance(task, self.Task) + ret = await task + self.assertEqual(1, ret) + + self.loop.run_until_complete(coro()) + def add_subclass_tests(cls): BaseTask = cls.Task diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 560db9f562d..a1a9bb3684c 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -28,6 +28,7 @@ from asyncio import base_events from asyncio import events +from asyncio import format_helpers from asyncio import futures from asyncio import tasks from asyncio.log import logger @@ -429,7 +430,7 @@ def __eq__(self, other): def get_function_source(func): - source = events._get_function_source(func) + source = format_helpers._get_function_source(func) if source is None: raise ValueError("unable to get the source of %r" % (func,)) return source diff --git a/Misc/NEWS.d/next/Library/2017-12-14-17-28-54.bpo-32311.DL5Ytn.rst b/Misc/NEWS.d/next/Library/2017-12-14-17-28-54.bpo-32311.DL5Ytn.rst new file mode 100644 index 00000000000..e2d10959476 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-14-17-28-54.bpo-32311.DL5Ytn.rst @@ -0,0 +1 @@ +Implement asyncio.create_task(coro) shortcut diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 01c38b80b95..9ac1c44d48d 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -26,6 +26,7 @@ static PyObject *all_tasks; static PyObject *current_tasks; static PyObject *traceback_extract_stack; static PyObject *asyncio_get_event_loop_policy; +static PyObject *asyncio_iscoroutine_func; static PyObject *asyncio_future_repr_info_func; static PyObject *asyncio_task_repr_info_func; static PyObject *asyncio_task_get_stack_func; @@ -1461,16 +1462,38 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) /*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/ { PyObject *res; + int tmp; _Py_IDENTIFIER(add); if (future_init((FutureObj*)self, loop)) { return -1; } + if (!PyCoro_CheckExact(coro)) { + // fastpath failed, perfom slow check + // raise after Future.__init__(), attrs are required for __del__ + res = PyObject_CallFunctionObjArgs(asyncio_iscoroutine_func, + coro, NULL); + if (res == NULL) { + return -1; + } + tmp = PyObject_Not(res); + Py_DECREF(res); + if (tmp < 0) { + return -1; + } + if (tmp) { + self->task_log_destroy_pending = 0; + PyErr_Format(PyExc_TypeError, + "a coroutine was expected, got %R", + coro, NULL); + return -1; + } + } + self->task_fut_waiter = NULL; self->task_must_cancel = 0; self->task_log_destroy_pending = 1; - Py_INCREF(coro); self->task_coro = coro; @@ -2604,6 +2627,7 @@ module_free(void *m) Py_CLEAR(traceback_extract_stack); Py_CLEAR(asyncio_get_event_loop_policy); Py_CLEAR(asyncio_future_repr_info_func); + Py_CLEAR(asyncio_iscoroutine_func); Py_CLEAR(asyncio_task_repr_info_func); Py_CLEAR(asyncio_task_get_stack_func); Py_CLEAR(asyncio_task_print_stack_func); @@ -2645,6 +2669,9 @@ module_init(void) GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack") GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack") + WITH_MOD("asyncio.coroutines") + GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine") + WITH_MOD("inspect") GET_MOD_ATTR(inspect_isgenerator, "isgenerator") From webhook-mailer at python.org Fri Dec 15 02:48:15 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 15 Dec 2017 07:48:15 -0000 Subject: [Python-checkins] move pygetopt.h to internal (closes bpo-32264) (#4830) Message-ID: https://github.com/python/cpython/commit/e425bd75177ffb7f098bdb0618b4a5ba3211fe52 commit: e425bd75177ffb7f098bdb0618b4a5ba3211fe52 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-14T23:48:12-08:00 summary: move pygetopt.h to internal (closes bpo-32264) (#4830) files: A Include/internal/pygetopt.h A Misc/NEWS.d/next/C API/2017-12-12-23-09-46.bpo-32264.ahRlOI.rst D Include/pygetopt.h M Makefile.pre.in M Modules/main.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/getopt.c diff --git a/Include/internal/pygetopt.h b/Include/internal/pygetopt.h new file mode 100644 index 00000000000..df6f18354ee --- /dev/null +++ b/Include/internal/pygetopt.h @@ -0,0 +1,19 @@ +#ifndef Py_INTERNAL_PYGETOPT_H +#define Py_INTERNAL_PYGETOPT_H + +int _PyOS_opterr; +int _PyOS_optind; +wchar_t *_PyOS_optarg; + +void _PyOS_ResetGetOpt(void); + +typedef struct { + const wchar_t *name; + int has_arg; + int val; +} _PyOS_LongOption; + +int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring, + const _PyOS_LongOption *longopts, int *longindex); + +#endif /* !Py_INTERNAL_PYGETOPT_H */ diff --git a/Include/pygetopt.h b/Include/pygetopt.h deleted file mode 100644 index 3e3fe364901..00000000000 --- a/Include/pygetopt.h +++ /dev/null @@ -1,28 +0,0 @@ - -#ifndef Py_PYGETOPT_H -#define Py_PYGETOPT_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_LIMITED_API -PyAPI_DATA(int) _PyOS_opterr; -PyAPI_DATA(int) _PyOS_optind; -PyAPI_DATA(wchar_t *) _PyOS_optarg; - -PyAPI_FUNC(void) _PyOS_ResetGetOpt(void); - -typedef struct { - const wchar_t *name; - int has_arg; - int val; -} _PyOS_LongOption; - -PyAPI_FUNC(int) _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring, - const _PyOS_LongOption *longopts, int *longindex); -#endif /* !Py_LIMITED_API */ - -#ifdef __cplusplus -} -#endif -#endif /* !Py_PYGETOPT_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index fcce62f2577..4fe9affe0d2 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -987,7 +987,6 @@ PYTHON_HEADERS= \ $(srcdir)/Include/pyhash.h \ $(srcdir)/Include/pylifecycle.h \ $(srcdir)/Include/pymath.h \ - $(srcdir)/Include/pygetopt.h \ $(srcdir)/Include/pymacro.h \ $(srcdir)/Include/pymem.h \ $(srcdir)/Include/pyport.h \ @@ -1017,6 +1016,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/ceval.h \ $(srcdir)/Include/internal/gil.h \ $(srcdir)/Include/internal/mem.h \ + $(srcdir)/Include/internal/pygetopt.h \ $(srcdir)/Include/internal/pystate.h \ $(srcdir)/Include/internal/warnings.h \ $(DTRACE_HEADERS) diff --git a/Misc/NEWS.d/next/C API/2017-12-12-23-09-46.bpo-32264.ahRlOI.rst b/Misc/NEWS.d/next/C API/2017-12-12-23-09-46.bpo-32264.ahRlOI.rst new file mode 100644 index 00000000000..5033d61a676 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2017-12-12-23-09-46.bpo-32264.ahRlOI.rst @@ -0,0 +1 @@ +Moved the pygetopt.h header into internal/, since it has no public APIs. diff --git a/Modules/main.c b/Modules/main.c index 339a0f5e681..6b602cf9b77 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -3,6 +3,7 @@ #include "Python.h" #include "osdefs.h" #include "internal/import.h" +#include "internal/pygetopt.h" #include "internal/pystate.h" #include @@ -27,8 +28,6 @@ #define PYTHONHOMEHELP "/lib/pythonX.X" #endif -#include "pygetopt.h" - #define COPYRIGHT \ "Type \"help\", \"copyright\", \"credits\" or \"license\" " \ "for more information." diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 1dca3ccca1d..25651d00049 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -150,7 +150,7 @@ - + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 969ba0850b2..42b2fc3ea7c 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -234,7 +234,7 @@ Include - + Include diff --git a/Python/getopt.c b/Python/getopt.c index de32ad4d8cb..e8d7e523c2e 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include "internal/pygetopt.h" #ifdef __cplusplus extern "C" { From solipsis at pitrou.net Fri Dec 15 04:10:25 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 15 Dec 2017 09:10:25 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=73 Message-ID: <20171215091025.26314.20470440CD6305E2@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 1] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [0, 0, 44] references, sum=44 test_multiprocessing_forkserver leaked [-1, 1, 22] memory blocks, sum=22 test_multiprocessing_forkserver leaked [0, 0, 2] file descriptors, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogIrvz1P', '--timeout', '7200'] From webhook-mailer at python.org Fri Dec 15 05:19:30 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 10:19:30 -0000 Subject: [Python-checkins] bpo-28393: Update encoding lookup docs wrt bpo-27938 (#4871) Message-ID: https://github.com/python/cpython/commit/297fd876aad8ef443d8992618de22c46dbda258b commit: 297fd876aad8ef443d8992618de22c46dbda258b branch: master author: Ville Skytt? committer: Victor Stinner date: 2017-12-15T11:19:23+01:00 summary: bpo-28393: Update encoding lookup docs wrt bpo-27938 (#4871) files: M Doc/library/codecs.rst diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 6e249ecf2b1..74b24e10ede 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -977,10 +977,14 @@ e.g. ``'utf-8'`` is a valid alias for the ``'utf_8'`` codec. Some common encodings can bypass the codecs lookup machinery to improve performance. These optimization opportunities are only - recognized by CPython for a limited set of aliases: utf-8, utf8, - latin-1, latin1, iso-8859-1, mbcs (Windows only), ascii, utf-16, - and utf-32. Using alternative spellings for these encodings may - result in slower execution. + recognized by CPython for a limited set of (case insensitive) + aliases: utf-8, utf8, latin-1, latin1, iso-8859-1, iso8859-1, mbcs + (Windows only), ascii, us-ascii, utf-16, utf16, utf-32, utf32, and + the same using underscores instead of dashes. Using alternative + aliases for these encodings may result in slower execution. + + .. versionchanged:: 3.6 + Optimization opportunity recognized for us-ascii. Many of the character sets support the same languages. They vary in individual characters (e.g. whether the EURO SIGN is supported or not), and in the From webhook-mailer at python.org Fri Dec 15 05:35:51 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 15 Dec 2017 10:35:51 -0000 Subject: [Python-checkins] bpo-27169: The __debug__ constant is now optimized out at compile time. (#4880) Message-ID: https://github.com/python/cpython/commit/3325a6780c81f1ea51190370b5454879c4862a37 commit: 3325a6780c81f1ea51190370b5454879c4862a37 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-15T12:35:48+02:00 summary: bpo-27169: The __debug__ constant is now optimized out at compile time. (#4880) This fixes also bpo-22091. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst M Lib/test/test_builtin.py M Lib/test/test_compile.py M Python/compile.c diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 9329318706b..8f91bc9bf91 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -337,16 +337,16 @@ def test_compile(self): try: assert False except AssertionError: - return (True, f.__doc__, debug_enabled) + return (True, f.__doc__, debug_enabled, __debug__) else: - return (False, f.__doc__, debug_enabled) + return (False, f.__doc__, debug_enabled, __debug__) ''' def f(): """doc""" - values = [(-1, __debug__, f.__doc__, __debug__), - (0, True, 'doc', True), - (1, False, 'doc', False), - (2, False, None, False)] - for optval, assertval, docstring, debugval in values: + values = [(-1, __debug__, f.__doc__, __debug__, __debug__), + (0, True, 'doc', True, True), + (1, False, 'doc', False, False), + (2, False, None, False, False)] + for optval, *expected in values: # test both direct compilation and compilation via AST codeobjs = [] codeobjs.append(compile(codestr, "", "exec", optimize=optval)) @@ -356,7 +356,7 @@ def f(): """doc""" ns = {} exec(code, ns) rv = ns['f']() - self.assertEqual(rv, (assertval, docstring, debugval)) + self.assertEqual(rv, tuple(expected)) def test_delattr(self): sys.spam = 1 diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index b4a52a53105..ae3043af0bd 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -35,6 +35,7 @@ def test_debug_assignment(self): import builtins prev = builtins.__debug__ setattr(builtins, '__debug__', 'sure') + self.assertEqual(__debug__, prev) setattr(builtins, '__debug__', prev) def test_argument_handling(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst new file mode 100644 index 00000000000..81d1d15cbbd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst @@ -0,0 +1,2 @@ +The ``__debug__`` constant is now optimized out at compile time. This fixes also +bpo-22091. diff --git a/Python/compile.c b/Python/compile.c index 3fd849108cc..51c9a08162c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1332,13 +1332,15 @@ is_const(expr_ty e) case Ellipsis_kind: case NameConstant_kind: return 1; + case Name_kind: + return _PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__"); default: return 0; } } static PyObject * -get_const_value(expr_ty e) +get_const_value(struct compiler *c, expr_ty e) { switch (e->kind) { case Constant_kind: @@ -1353,6 +1355,9 @@ get_const_value(expr_ty e) return Py_Ellipsis; case NameConstant_kind: return e->v.NameConstant.value; + case Name_kind: + assert(_PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__")); + return c->c_optimize ? Py_False : Py_True; default: Py_UNREACHABLE(); } @@ -3097,6 +3102,11 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) !_PyUnicode_EqualToASCIIString(name, "True") && !_PyUnicode_EqualToASCIIString(name, "False")); + if (ctx == Load && _PyUnicode_EqualToASCIIString(name, "__debug__")) { + ADDOP_O(c, LOAD_CONST, c->c_optimize ? Py_False : Py_True, consts); + return 1; + } + op = 0; optype = OP_NAME; scope = PyST_GetScope(c->u->u_ste, mangled); @@ -3360,7 +3370,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end return 0; } for (i = begin; i < end; i++) { - key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + key = get_const_value(c, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); Py_INCREF(key); PyTuple_SET_ITEM(keys, i - begin, key); } @@ -4132,35 +4142,10 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int expr_constant(struct compiler *c, expr_ty e) { - const char *id; - switch (e->kind) { - case Ellipsis_kind: - return 1; - case Constant_kind: - return PyObject_IsTrue(e->v.Constant.value); - case Num_kind: - return PyObject_IsTrue(e->v.Num.n); - case Str_kind: - return PyObject_IsTrue(e->v.Str.s); - case Name_kind: - /* optimize away names that can't be reassigned */ - id = PyUnicode_AsUTF8(e->v.Name.id); - if (id && strcmp(id, "__debug__") == 0) - return !c->c_optimize; - return -1; - case NameConstant_kind: { - PyObject *o = e->v.NameConstant.value; - if (o == Py_None) - return 0; - else if (o == Py_True) - return 1; - else if (o == Py_False) - return 0; - } - /* fall through */ - default: - return -1; + if (is_const(e)) { + return PyObject_IsTrue(get_const_value(c, e)); } + return -1; } From webhook-mailer at python.org Fri Dec 15 06:11:15 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 15 Dec 2017 11:11:15 -0000 Subject: [Python-checkins] bpo-32240: Add the const qualifier to declarations of PyObject* array arguments. (#4746) Message-ID: https://github.com/python/cpython/commit/a5552f023e1d8cbafee1e51d316cc581deb2295f commit: a5552f023e1d8cbafee1e51d316cc581deb2295f branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-15T13:11:11+02:00 summary: bpo-32240: Add the const qualifier to declarations of PyObject* array arguments. (#4746) files: M Doc/c-api/veryhigh.rst M Include/abstract.h M Include/descrobject.h M Include/eval.h M Include/funcobject.h M Include/methodobject.h M Include/modsupport.h M Include/unicodeobject.h M Modules/_collectionsmodule.c M Modules/_elementtree.c M Modules/_hashopenssl.c M Modules/_io/clinic/_iomodule.c.h M Modules/_io/clinic/bufferedio.c.h M Modules/_io/clinic/bytesio.c.h M Modules/_io/clinic/fileio.c.h M Modules/_io/clinic/iobase.c.h M Modules/_io/clinic/stringio.c.h M Modules/_io/clinic/textio.c.h M Modules/_io/clinic/winconsoleio.c.h M Modules/_sha3/clinic/sha3module.c.h M Modules/_struct.c M Modules/cjkcodecs/clinic/multibytecodec.c.h M Modules/clinic/_asynciomodule.c.h M Modules/clinic/_bz2module.c.h M Modules/clinic/_codecsmodule.c.h M Modules/clinic/_cryptmodule.c.h M Modules/clinic/_datetimemodule.c.h M Modules/clinic/_dbmmodule.c.h M Modules/clinic/_elementtree.c.h M Modules/clinic/_gdbmmodule.c.h M Modules/clinic/_hashopenssl.c.h M Modules/clinic/_lzmamodule.c.h M Modules/clinic/_opcode.c.h M Modules/clinic/_operator.c.h M Modules/clinic/_pickle.c.h M Modules/clinic/_sre.c.h M Modules/clinic/_ssl.c.h M Modules/clinic/_struct.c.h M Modules/clinic/_tkinter.c.h M Modules/clinic/_tracemalloc.c.h M Modules/clinic/_weakref.c.h M Modules/clinic/_winapi.c.h M Modules/clinic/arraymodule.c.h M Modules/clinic/audioop.c.h M Modules/clinic/binascii.c.h M Modules/clinic/cmathmodule.c.h M Modules/clinic/fcntlmodule.c.h M Modules/clinic/gcmodule.c.h M Modules/clinic/grpmodule.c.h M Modules/clinic/mathmodule.c.h M Modules/clinic/md5module.c.h M Modules/clinic/posixmodule.c.h M Modules/clinic/pyexpat.c.h M Modules/clinic/resource.c.h M Modules/clinic/sha1module.c.h M Modules/clinic/sha256module.c.h M Modules/clinic/sha512module.c.h M Modules/clinic/signalmodule.c.h M Modules/clinic/symtablemodule.c.h M Modules/clinic/unicodedata.c.h M Modules/clinic/zipimport.c.h M Modules/clinic/zlibmodule.c.h M Objects/call.c M Objects/clinic/bytearrayobject.c.h M Objects/clinic/bytesobject.c.h M Objects/clinic/dictobject.c.h M Objects/clinic/floatobject.c.h M Objects/clinic/listobject.c.h M Objects/clinic/longobject.c.h M Objects/clinic/odictobject.c.h M Objects/clinic/tupleobject.c.h M Objects/clinic/unicodeobject.c.h M Objects/descrobject.c M Objects/typeobject.c M Objects/unicodeobject.c M PC/clinic/_testconsole.c.h M PC/clinic/msvcrtmodule.c.h M PC/clinic/winreg.c.h M PC/clinic/winsound.c.h M Python/bltinmodule.c M Python/ceval.c M Python/clinic/_warnings.c.h M Python/clinic/bltinmodule.c.h M Python/clinic/import.c.h M Python/clinic/marshal.c.h M Python/getargs.c M Python/sysmodule.c M Tools/clinic/clinic.py diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 3897fdd8282..cefe9d44bf4 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -301,7 +301,7 @@ the same library that the Python runtime is using. set to *NULL*. -.. c:function:: PyObject* PyEval_EvalCodeEx(PyObject *co, PyObject *globals, PyObject *locals, PyObject **args, int argcount, PyObject **kws, int kwcount, PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) +.. c:function:: PyObject* PyEval_EvalCodeEx(PyObject *co, PyObject *globals, PyObject *locals, PyObject *const *args, int argcount, PyObject *const *kws, int kwcount, PyObject *const *defs, int defcount, PyObject *kwdefs, PyObject *closure) Evaluate a precompiled code object, given a particular environment for its evaluation. This environment consists of a dictionary of global variables, diff --git a/Include/abstract.h b/Include/abstract.h index 8969019e30c..991c1c3ee00 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -157,11 +157,11 @@ PyAPI_FUNC(PyObject *) PyObject_Call(PyObject *callable, #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject*) _PyStack_AsTuple( - PyObject **stack, + PyObject *const *stack, Py_ssize_t nargs); PyAPI_FUNC(PyObject*) _PyStack_AsTupleSlice( - PyObject **stack, + PyObject *const *stack, Py_ssize_t nargs, Py_ssize_t start, Py_ssize_t end); @@ -177,7 +177,7 @@ PyAPI_FUNC(PyObject*) _PyStack_AsTupleSlice( an exception, the caller is responsible to implement an explicit keys on kwnames. */ PyAPI_FUNC(PyObject *) _PyStack_AsDict( - PyObject **values, + PyObject *const *values, PyObject *kwnames); /* Convert (args, nargs, kwargs: dict) into a (stack, nargs, kwnames: tuple). @@ -192,10 +192,10 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict( The type of keyword keys is not checked, these checks should be done later (ex: _PyArg_ParseStackAndKeywords). */ PyAPI_FUNC(int) _PyStack_UnpackDict( - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, - PyObject ***p_stack, + PyObject *const **p_stack, PyObject **p_kwnames); /* Suggested size (number of positional arguments) for arrays of PyObject* @@ -224,7 +224,7 @@ PyAPI_FUNC(int) _PyObject_HasFastCall(PyObject *callable); error. */ PyAPI_FUNC(PyObject *) _PyObject_FastCallDict( PyObject *callable, - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs); @@ -245,7 +245,7 @@ PyAPI_FUNC(PyObject *) _PyObject_FastCallDict( error. */ PyAPI_FUNC(PyObject *) _PyObject_FastCallKeywords( PyObject *callable, - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); @@ -264,7 +264,7 @@ PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend( PyAPI_FUNC(PyObject *) _PyObject_FastCall_Prepend( PyObject *callable, PyObject *obj, - PyObject **args, + PyObject *const *args, Py_ssize_t nargs); PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *callable, diff --git a/Include/descrobject.h b/Include/descrobject.h index cb43174838a..73bbb3fe54e 100644 --- a/Include/descrobject.h +++ b/Include/descrobject.h @@ -92,7 +92,7 @@ PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _PyMethodDescr_FastCallKeywords( - PyObject *descrobj, PyObject **stack, Py_ssize_t nargs, PyObject *kwnames); + PyObject *descrobj, PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames); PyAPI_FUNC(PyObject *) PyDescr_NewWrapper(PyTypeObject *, struct wrapperbase *, void *); #define PyDescr_IsData(d) (Py_TYPE(d)->tp_descr_set != NULL) diff --git a/Include/eval.h b/Include/eval.h index 9541e106e29..2c1c2d0549a 100644 --- a/Include/eval.h +++ b/Include/eval.h @@ -12,19 +12,19 @@ PyAPI_FUNC(PyObject *) PyEval_EvalCode(PyObject *, PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyObject *co, PyObject *globals, PyObject *locals, - PyObject **args, int argc, - PyObject **kwds, int kwdc, - PyObject **defs, int defc, + PyObject *const *args, int argc, + PyObject *const *kwds, int kwdc, + PyObject *const *defs, int defc, PyObject *kwdefs, PyObject *closure); #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _PyEval_EvalCodeWithName( PyObject *co, PyObject *globals, PyObject *locals, - PyObject **args, Py_ssize_t argcount, - PyObject **kwnames, PyObject **kwargs, + PyObject *const *args, Py_ssize_t argcount, + PyObject *const *kwnames, PyObject *const *kwargs, Py_ssize_t kwcount, int kwstep, - PyObject **defs, Py_ssize_t defcount, + PyObject *const *defs, Py_ssize_t defcount, PyObject *kwdefs, PyObject *closure, PyObject *name, PyObject *qualname); diff --git a/Include/funcobject.h b/Include/funcobject.h index 89305dcf768..86674ac90a0 100644 --- a/Include/funcobject.h +++ b/Include/funcobject.h @@ -61,13 +61,13 @@ PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *); #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _PyFunction_FastCallDict( PyObject *func, - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs); PyAPI_FUNC(PyObject *) _PyFunction_FastCallKeywords( PyObject *func, - PyObject **stack, + PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames); #endif diff --git a/Include/methodobject.h b/Include/methodobject.h index 66e6a554b11..ea35d86bcd1 100644 --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -16,11 +16,11 @@ PyAPI_DATA(PyTypeObject) PyCFunction_Type; #define PyCFunction_Check(op) (Py_TYPE(op) == &PyCFunction_Type) typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); -typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject **, Py_ssize_t); +typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t); typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *, PyObject *); typedef PyObject *(*_PyCFunctionFastWithKeywords) (PyObject *, - PyObject **, Py_ssize_t, + PyObject *const *, Py_ssize_t, PyObject *); typedef PyObject *(*PyNoArgsFunction)(PyObject *); @@ -43,12 +43,12 @@ PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _PyCFunction_FastCallDict(PyObject *func, - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs); PyAPI_FUNC(PyObject *) _PyCFunction_FastCallKeywords(PyObject *func, - PyObject **stack, + PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames); #endif @@ -110,14 +110,14 @@ typedef struct { PyAPI_FUNC(PyObject *) _PyMethodDef_RawFastCallDict( PyMethodDef *method, PyObject *self, - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs); PyAPI_FUNC(PyObject *) _PyMethodDef_RawFastCallKeywords( PyMethodDef *method, PyObject *self, - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); #endif diff --git a/Include/modsupport.h b/Include/modsupport.h index 73d86a94b95..a238bef03cb 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -52,7 +52,7 @@ PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyArg_UnpackStack( - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, const char *name, Py_ssize_t min, @@ -99,12 +99,12 @@ typedef struct _PyArg_Parser { PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, struct _PyArg_Parser *, ...); PyAPI_FUNC(int) _PyArg_ParseStack( - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, const char *format, ...); PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords( - PyObject **args, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, struct _PyArg_Parser *, diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 61e713be072..0274de6733a 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -1979,7 +1979,7 @@ PyAPI_FUNC(PyObject*) PyUnicode_Join( #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _PyUnicode_JoinArray( PyObject *separator, - PyObject **items, + PyObject *const *items, Py_ssize_t seqlen ); #endif /* Py_LIMITED_API */ diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index b6cceee27f5..222cace5af7 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -912,7 +912,7 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n) } static PyObject * -deque_rotate(dequeobject *deque, PyObject **args, Py_ssize_t nargs) +deque_rotate(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) { Py_ssize_t n=1; @@ -1045,7 +1045,7 @@ deque_len(dequeobject *deque) } static PyObject * -deque_index(dequeobject *deque, PyObject **args, Py_ssize_t nargs) +deque_index(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) { Py_ssize_t i, n, start=0, stop=Py_SIZE(deque); PyObject *v, *item; @@ -1122,7 +1122,7 @@ PyDoc_STRVAR(index_doc, */ static PyObject * -deque_insert(dequeobject *deque, PyObject **args, Py_ssize_t nargs) +deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) { Py_ssize_t index; Py_ssize_t n = Py_SIZE(deque); diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index b4c0f4c87a8..1dfdb3ce34f 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2771,7 +2771,7 @@ typedef struct { } XMLParserObject; static PyObject* -_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject **args, Py_ssize_t nargs); +_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject *const *args, Py_ssize_t nargs); static PyObject * _elementtree_XMLParser_doctype_impl(XMLParserObject *self, PyObject *name, PyObject *pubid, PyObject *system); diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index d597987b442..c8d175860b7 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -915,7 +915,7 @@ generate_hash_name_list(void) */ #define GEN_CONSTRUCTOR(NAME) \ static PyObject * \ - EVP_new_ ## NAME (PyObject *self, PyObject **args, Py_ssize_t nargs) \ + EVP_new_ ## NAME (PyObject *self, PyObject *const *args, Py_ssize_t nargs) \ { \ PyObject *data_obj = NULL; \ Py_buffer view = { 0 }; \ diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h index 3d6d5c7e04b..b8ae2ce34eb 100644 --- a/Modules/_io/clinic/_iomodule.c.h +++ b/Modules/_io/clinic/_iomodule.c.h @@ -135,7 +135,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, const char *newline, int closefd, PyObject *opener); static PyObject * -_io_open(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", NULL}; @@ -158,4 +158,4 @@ _io_open(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) exit: return return_value; } -/*[clinic end generated code: output=7e0ab289d8465580 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a9de1ae79c960e81 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index fafcc129152..7b93929675f 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -97,7 +97,7 @@ static PyObject * _io__Buffered_peek_impl(buffered *self, Py_ssize_t size); static PyObject * -_io__Buffered_peek(buffered *self, PyObject **args, Py_ssize_t nargs) +_io__Buffered_peek(buffered *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = 0; @@ -124,7 +124,7 @@ static PyObject * _io__Buffered_read_impl(buffered *self, Py_ssize_t n); static PyObject * -_io__Buffered_read(buffered *self, PyObject **args, Py_ssize_t nargs) +_io__Buffered_read(buffered *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t n = -1; @@ -151,7 +151,7 @@ static PyObject * _io__Buffered_read1_impl(buffered *self, Py_ssize_t n); static PyObject * -_io__Buffered_read1(buffered *self, PyObject **args, Py_ssize_t nargs) +_io__Buffered_read1(buffered *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t n = -1; @@ -240,7 +240,7 @@ static PyObject * _io__Buffered_readline_impl(buffered *self, Py_ssize_t size); static PyObject * -_io__Buffered_readline(buffered *self, PyObject **args, Py_ssize_t nargs) +_io__Buffered_readline(buffered *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -267,7 +267,7 @@ static PyObject * _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence); static PyObject * -_io__Buffered_seek(buffered *self, PyObject **args, Py_ssize_t nargs) +_io__Buffered_seek(buffered *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *targetobj; @@ -295,7 +295,7 @@ static PyObject * _io__Buffered_truncate_impl(buffered *self, PyObject *pos); static PyObject * -_io__Buffered_truncate(buffered *self, PyObject **args, Py_ssize_t nargs) +_io__Buffered_truncate(buffered *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *pos = Py_None; @@ -476,4 +476,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=2b817df0bf814ddc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9a20dd4eaabb5d58 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h index c9203325965..5c155cb3066 100644 --- a/Modules/_io/clinic/bytesio.c.h +++ b/Modules/_io/clinic/bytesio.c.h @@ -164,7 +164,7 @@ static PyObject * _io_BytesIO_read_impl(bytesio *self, Py_ssize_t size); static PyObject * -_io_BytesIO_read(bytesio *self, PyObject **args, Py_ssize_t nargs) +_io_BytesIO_read(bytesio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -195,7 +195,7 @@ static PyObject * _io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size); static PyObject * -_io_BytesIO_read1(bytesio *self, PyObject **args, Py_ssize_t nargs) +_io_BytesIO_read1(bytesio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -227,7 +227,7 @@ static PyObject * _io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size); static PyObject * -_io_BytesIO_readline(bytesio *self, PyObject **args, Py_ssize_t nargs) +_io_BytesIO_readline(bytesio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -259,7 +259,7 @@ static PyObject * _io_BytesIO_readlines_impl(bytesio *self, PyObject *arg); static PyObject * -_io_BytesIO_readlines(bytesio *self, PyObject **args, Py_ssize_t nargs) +_io_BytesIO_readlines(bytesio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *arg = Py_None; @@ -326,7 +326,7 @@ static PyObject * _io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size); static PyObject * -_io_BytesIO_truncate(bytesio *self, PyObject **args, Py_ssize_t nargs) +_io_BytesIO_truncate(bytesio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = self->pos; @@ -360,7 +360,7 @@ static PyObject * _io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence); static PyObject * -_io_BytesIO_seek(bytesio *self, PyObject **args, Py_ssize_t nargs) +_io_BytesIO_seek(bytesio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t pos; @@ -444,4 +444,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=20946f5a2ed4492b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9ba9a68c8c5669e7 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h index 720e7226557..8a9958aaecf 100644 --- a/Modules/_io/clinic/fileio.c.h +++ b/Modules/_io/clinic/fileio.c.h @@ -208,7 +208,7 @@ static PyObject * _io_FileIO_read_impl(fileio *self, Py_ssize_t size); static PyObject * -_io_FileIO_read(fileio *self, PyObject **args, Py_ssize_t nargs) +_io_FileIO_read(fileio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -280,7 +280,7 @@ static PyObject * _io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence); static PyObject * -_io_FileIO_seek(fileio *self, PyObject **args, Py_ssize_t nargs) +_io_FileIO_seek(fileio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *pos; @@ -334,7 +334,7 @@ static PyObject * _io_FileIO_truncate_impl(fileio *self, PyObject *posobj); static PyObject * -_io_FileIO_truncate(fileio *self, PyObject **args, Py_ssize_t nargs) +_io_FileIO_truncate(fileio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *posobj = NULL; @@ -373,4 +373,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=1af8b4031633b763 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a8796438c8b7c49a input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h index 2ab61a816bf..e6f72cd5ff9 100644 --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -180,7 +180,7 @@ static PyObject * _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit); static PyObject * -_io__IOBase_readline(PyObject *self, PyObject **args, Py_ssize_t nargs) +_io__IOBase_readline(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t limit = -1; @@ -212,7 +212,7 @@ static PyObject * _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint); static PyObject * -_io__IOBase_readlines(PyObject *self, PyObject **args, Py_ssize_t nargs) +_io__IOBase_readlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t hint = -1; @@ -247,7 +247,7 @@ static PyObject * _io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n); static PyObject * -_io__RawIOBase_read(PyObject *self, PyObject **args, Py_ssize_t nargs) +_io__RawIOBase_read(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t n = -1; @@ -279,4 +279,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=1dc5cc1a9977d73f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=64989ec3dbf44a7c input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/stringio.c.h b/Modules/_io/clinic/stringio.c.h index d0d429698ec..72b2540d47a 100644 --- a/Modules/_io/clinic/stringio.c.h +++ b/Modules/_io/clinic/stringio.c.h @@ -54,7 +54,7 @@ static PyObject * _io_StringIO_read_impl(stringio *self, Py_ssize_t size); static PyObject * -_io_StringIO_read(stringio *self, PyObject **args, Py_ssize_t nargs) +_io_StringIO_read(stringio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -84,7 +84,7 @@ static PyObject * _io_StringIO_readline_impl(stringio *self, Py_ssize_t size); static PyObject * -_io_StringIO_readline(stringio *self, PyObject **args, Py_ssize_t nargs) +_io_StringIO_readline(stringio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -116,7 +116,7 @@ static PyObject * _io_StringIO_truncate_impl(stringio *self, Py_ssize_t size); static PyObject * -_io_StringIO_truncate(stringio *self, PyObject **args, Py_ssize_t nargs) +_io_StringIO_truncate(stringio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = self->pos; @@ -150,7 +150,7 @@ static PyObject * _io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence); static PyObject * -_io_StringIO_seek(stringio *self, PyObject **args, Py_ssize_t nargs) +_io_StringIO_seek(stringio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t pos; @@ -286,4 +286,4 @@ _io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored)) { return _io_StringIO_seekable_impl(self); } -/*[clinic end generated code: output=a5e963d90b4eedc0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=73c4d6e5cc3b1a58 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index a42800507c3..53ac0de89ab 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -53,7 +53,7 @@ _io_IncrementalNewlineDecoder_decode_impl(nldecoder_object *self, PyObject *input, int final); static PyObject * -_io_IncrementalNewlineDecoder_decode(nldecoder_object *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_io_IncrementalNewlineDecoder_decode(nldecoder_object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"input", "final", NULL}; @@ -193,7 +193,7 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *write_through_obj); static PyObject * -_io_TextIOWrapper_reconfigure(textio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_io_TextIOWrapper_reconfigure(textio *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"line_buffering", "write_through", NULL}; @@ -266,7 +266,7 @@ static PyObject * _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n); static PyObject * -_io_TextIOWrapper_read(textio *self, PyObject **args, Py_ssize_t nargs) +_io_TextIOWrapper_read(textio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t n = -1; @@ -293,7 +293,7 @@ static PyObject * _io_TextIOWrapper_readline_impl(textio *self, Py_ssize_t size); static PyObject * -_io_TextIOWrapper_readline(textio *self, PyObject **args, Py_ssize_t nargs) +_io_TextIOWrapper_readline(textio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -320,7 +320,7 @@ static PyObject * _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence); static PyObject * -_io_TextIOWrapper_seek(textio *self, PyObject **args, Py_ssize_t nargs) +_io_TextIOWrapper_seek(textio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *cookieObj; @@ -365,7 +365,7 @@ static PyObject * _io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos); static PyObject * -_io_TextIOWrapper_truncate(textio *self, PyObject **args, Py_ssize_t nargs) +_io_TextIOWrapper_truncate(textio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *pos = Py_None; @@ -499,4 +499,4 @@ _io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { return _io_TextIOWrapper_close_impl(self); } -/*[clinic end generated code: output=937989df0a8abfc3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=679b3ac5284df4e0 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/winconsoleio.c.h b/Modules/_io/clinic/winconsoleio.c.h index 94153451382..2291225ead3 100644 --- a/Modules/_io/clinic/winconsoleio.c.h +++ b/Modules/_io/clinic/winconsoleio.c.h @@ -215,7 +215,7 @@ static PyObject * _io__WindowsConsoleIO_read_impl(winconsoleio *self, Py_ssize_t size); static PyObject * -_io__WindowsConsoleIO_read(winconsoleio *self, PyObject **args, Py_ssize_t nargs) +_io__WindowsConsoleIO_read(winconsoleio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t size = -1; @@ -328,4 +328,4 @@ _io__WindowsConsoleIO_isatty(winconsoleio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */ -/*[clinic end generated code: output=7f74992fcd5bd89d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6d351a8200a8e848 input=a9049054013a1b77]*/ diff --git a/Modules/_sha3/clinic/sha3module.c.h b/Modules/_sha3/clinic/sha3module.c.h index b345ccde77d..a1e80b061e5 100644 --- a/Modules/_sha3/clinic/sha3module.c.h +++ b/Modules/_sha3/clinic/sha3module.c.h @@ -105,7 +105,7 @@ static PyObject * _sha3_shake_128_digest_impl(SHA3object *self, unsigned long length); static PyObject * -_sha3_shake_128_digest(SHA3object *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sha3_shake_128_digest(SHA3object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"length", NULL}; @@ -135,7 +135,7 @@ static PyObject * _sha3_shake_128_hexdigest_impl(SHA3object *self, unsigned long length); static PyObject * -_sha3_shake_128_hexdigest(SHA3object *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sha3_shake_128_hexdigest(SHA3object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"length", NULL}; @@ -151,4 +151,4 @@ _sha3_shake_128_hexdigest(SHA3object *self, PyObject **args, Py_ssize_t nargs, P exit: return return_value; } -/*[clinic end generated code: output=7c1ac102411764f2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a3aeb6c3b2fbd905 input=a9049054013a1b77]*/ diff --git a/Modules/_struct.c b/Modules/_struct.c index 04d7f8e1871..66f74d63b73 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1733,7 +1733,7 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer) * */ static int -s_pack_internal(PyStructObject *soself, PyObject **args, int offset, char* buf) +s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* buf) { formatcode *code; /* XXX(nnorwitz): why does i need to be a local? can we use @@ -1820,7 +1820,7 @@ to the format string S.format. See help(struct) for more on format\n\ strings."); static PyObject * -s_pack(PyObject *self, PyObject **args, Py_ssize_t nargs) +s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyStructObject *soself; PyObject *result; @@ -1859,7 +1859,7 @@ offset. Note that the offset is a required argument. See\n\ help(struct) for more on format strings."); static PyObject * -s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs) +s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyStructObject *soself; Py_buffer buffer; @@ -2123,7 +2123,7 @@ Return a bytes object containing the values v1, v2, ... packed according\n\ to the format string. See help(struct) for more on format strings."); static PyObject * -pack(PyObject *self, PyObject **args, Py_ssize_t nargs) +pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *s_object = NULL; PyObject *format, *result; @@ -2151,7 +2151,7 @@ that the offset is a required argument. See help(struct) for more\n\ on format strings."); static PyObject * -pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs) +pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *s_object = NULL; PyObject *format, *result; diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h index d0810adf65b..25857fc6d6f 100644 --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -22,7 +22,7 @@ _multibytecodec_MultibyteCodec_encode_impl(MultibyteCodecObject *self, const char *errors); static PyObject * -_multibytecodec_MultibyteCodec_encode(MultibyteCodecObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_multibytecodec_MultibyteCodec_encode(MultibyteCodecObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"input", "errors", NULL}; @@ -60,7 +60,7 @@ _multibytecodec_MultibyteCodec_decode_impl(MultibyteCodecObject *self, const char *errors); static PyObject * -_multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"input", "errors", NULL}; @@ -97,7 +97,7 @@ _multibytecodec_MultibyteIncrementalEncoder_encode_impl(MultibyteIncrementalEnco int final); static PyObject * -_multibytecodec_MultibyteIncrementalEncoder_encode(MultibyteIncrementalEncoderObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_multibytecodec_MultibyteIncrementalEncoder_encode(MultibyteIncrementalEncoderObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"input", "final", NULL}; @@ -146,7 +146,7 @@ _multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDeco int final); static PyObject * -_multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"input", "final", NULL}; @@ -199,7 +199,7 @@ _multibytecodec_MultibyteStreamReader_read_impl(MultibyteStreamReaderObject *sel PyObject *sizeobj); static PyObject * -_multibytecodec_MultibyteStreamReader_read(MultibyteStreamReaderObject *self, PyObject **args, Py_ssize_t nargs) +_multibytecodec_MultibyteStreamReader_read(MultibyteStreamReaderObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *sizeobj = Py_None; @@ -228,7 +228,7 @@ _multibytecodec_MultibyteStreamReader_readline_impl(MultibyteStreamReaderObject PyObject *sizeobj); static PyObject * -_multibytecodec_MultibyteStreamReader_readline(MultibyteStreamReaderObject *self, PyObject **args, Py_ssize_t nargs) +_multibytecodec_MultibyteStreamReader_readline(MultibyteStreamReaderObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *sizeobj = Py_None; @@ -257,7 +257,7 @@ _multibytecodec_MultibyteStreamReader_readlines_impl(MultibyteStreamReaderObject PyObject *sizehintobj); static PyObject * -_multibytecodec_MultibyteStreamReader_readlines(MultibyteStreamReaderObject *self, PyObject **args, Py_ssize_t nargs) +_multibytecodec_MultibyteStreamReader_readlines(MultibyteStreamReaderObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *sizehintobj = Py_None; @@ -330,4 +330,4 @@ PyDoc_STRVAR(_multibytecodec___create_codec__doc__, #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=dc2352619de9d74f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=680f59f4cfe63c25 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h index 8022d1c6f50..952316cc195 100644 --- a/Modules/clinic/_asynciomodule.c.h +++ b/Modules/clinic/_asynciomodule.c.h @@ -273,7 +273,7 @@ static PyObject * _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop); static PyObject * -_asyncio_Task_current_task(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_asyncio_Task_current_task(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"loop", NULL}; @@ -305,7 +305,7 @@ static PyObject * _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop); static PyObject * -_asyncio_Task_all_tasks(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_asyncio_Task_all_tasks(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"loop", NULL}; @@ -405,7 +405,7 @@ static PyObject * _asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit); static PyObject * -_asyncio_Task_get_stack(TaskObj *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_asyncio_Task_get_stack(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"limit", NULL}; @@ -442,7 +442,7 @@ _asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit, PyObject *file); static PyObject * -_asyncio_Task_print_stack(TaskObj *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_asyncio_Task_print_stack(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"limit", "file", NULL}; @@ -472,7 +472,7 @@ static PyObject * _asyncio_Task__step_impl(TaskObj *self, PyObject *exc); static PyObject * -_asyncio_Task__step(TaskObj *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_asyncio_Task__step(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"exc", NULL}; @@ -501,7 +501,7 @@ static PyObject * _asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut); static PyObject * -_asyncio_Task__wakeup(TaskObj *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_asyncio_Task__wakeup(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fut", NULL}; @@ -595,4 +595,4 @@ _asyncio_get_running_loop(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _asyncio_get_running_loop_impl(module); } -/*[clinic end generated code: output=d40b94e629571d48 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=21e5424c3a5572b0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h index 4ebdf7f5393..601bcc690d9 100644 --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -122,7 +122,7 @@ _bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, Py_ssize_t max_length); static PyObject * -_bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"data", "max_length", NULL}; @@ -174,4 +174,4 @@ _bz2_BZ2Decompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=835673574cf12cc4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=564a0313177fff63 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index f19d01da691..2f660fd3b4d 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -62,7 +62,7 @@ _codecs_encode_impl(PyObject *module, PyObject *obj, const char *encoding, const char *errors); static PyObject * -_codecs_encode(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_codecs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"obj", "encoding", "errors", NULL}; @@ -101,7 +101,7 @@ _codecs_decode_impl(PyObject *module, PyObject *obj, const char *encoding, const char *errors); static PyObject * -_codecs_decode(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_codecs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"obj", "encoding", "errors", NULL}; @@ -160,7 +160,7 @@ _codecs_escape_decode_impl(PyObject *module, Py_buffer *data, const char *errors); static PyObject * -_codecs_escape_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -194,7 +194,7 @@ _codecs_escape_encode_impl(PyObject *module, PyObject *data, const char *errors); static PyObject * -_codecs_escape_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *data; @@ -223,7 +223,7 @@ _codecs_unicode_internal_decode_impl(PyObject *module, PyObject *obj, const char *errors); static PyObject * -_codecs_unicode_internal_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_unicode_internal_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *obj; @@ -252,7 +252,7 @@ _codecs_utf_7_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_7_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_7_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -287,7 +287,7 @@ _codecs_utf_8_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_8_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_8_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -322,7 +322,7 @@ _codecs_utf_16_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_16_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_16_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -357,7 +357,7 @@ _codecs_utf_16_le_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_16_le_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_16_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -392,7 +392,7 @@ _codecs_utf_16_be_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_16_be_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_16_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -428,7 +428,7 @@ _codecs_utf_16_ex_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int byteorder, int final); static PyObject * -_codecs_utf_16_ex_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -464,7 +464,7 @@ _codecs_utf_32_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_32_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_32_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -499,7 +499,7 @@ _codecs_utf_32_le_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_32_le_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_32_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -534,7 +534,7 @@ _codecs_utf_32_be_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_utf_32_be_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_32_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -570,7 +570,7 @@ _codecs_utf_32_ex_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int byteorder, int final); static PyObject * -_codecs_utf_32_ex_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -606,7 +606,7 @@ _codecs_unicode_escape_decode_impl(PyObject *module, Py_buffer *data, const char *errors); static PyObject * -_codecs_unicode_escape_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -640,7 +640,7 @@ _codecs_raw_unicode_escape_decode_impl(PyObject *module, Py_buffer *data, const char *errors); static PyObject * -_codecs_raw_unicode_escape_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -674,7 +674,7 @@ _codecs_latin_1_decode_impl(PyObject *module, Py_buffer *data, const char *errors); static PyObject * -_codecs_latin_1_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_latin_1_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -708,7 +708,7 @@ _codecs_ascii_decode_impl(PyObject *module, Py_buffer *data, const char *errors); static PyObject * -_codecs_ascii_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_ascii_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -742,7 +742,7 @@ _codecs_charmap_decode_impl(PyObject *module, Py_buffer *data, const char *errors, PyObject *mapping); static PyObject * -_codecs_charmap_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_charmap_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -779,7 +779,7 @@ _codecs_mbcs_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_mbcs_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_mbcs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -818,7 +818,7 @@ _codecs_oem_decode_impl(PyObject *module, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_oem_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_oem_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -857,7 +857,7 @@ _codecs_code_page_decode_impl(PyObject *module, int codepage, Py_buffer *data, const char *errors, int final); static PyObject * -_codecs_code_page_decode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int codepage; @@ -895,7 +895,7 @@ _codecs_readbuffer_encode_impl(PyObject *module, Py_buffer *data, const char *errors); static PyObject * -_codecs_readbuffer_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_readbuffer_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -929,7 +929,7 @@ _codecs_unicode_internal_encode_impl(PyObject *module, PyObject *obj, const char *errors); static PyObject * -_codecs_unicode_internal_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_unicode_internal_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *obj; @@ -958,7 +958,7 @@ _codecs_utf_7_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_utf_7_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_7_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -987,7 +987,7 @@ _codecs_utf_8_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_utf_8_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_8_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1016,7 +1016,7 @@ _codecs_utf_16_encode_impl(PyObject *module, PyObject *str, const char *errors, int byteorder); static PyObject * -_codecs_utf_16_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_16_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1046,7 +1046,7 @@ _codecs_utf_16_le_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_utf_16_le_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_16_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1075,7 +1075,7 @@ _codecs_utf_16_be_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_utf_16_be_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_16_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1104,7 +1104,7 @@ _codecs_utf_32_encode_impl(PyObject *module, PyObject *str, const char *errors, int byteorder); static PyObject * -_codecs_utf_32_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_32_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1134,7 +1134,7 @@ _codecs_utf_32_le_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_utf_32_le_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_32_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1163,7 +1163,7 @@ _codecs_utf_32_be_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_utf_32_be_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_utf_32_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1192,7 +1192,7 @@ _codecs_unicode_escape_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_unicode_escape_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1221,7 +1221,7 @@ _codecs_raw_unicode_escape_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_raw_unicode_escape_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_raw_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1250,7 +1250,7 @@ _codecs_latin_1_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_latin_1_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_latin_1_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1279,7 +1279,7 @@ _codecs_ascii_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_ascii_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_ascii_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1308,7 +1308,7 @@ _codecs_charmap_encode_impl(PyObject *module, PyObject *str, const char *errors, PyObject *mapping); static PyObject * -_codecs_charmap_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_charmap_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1365,7 +1365,7 @@ static PyObject * _codecs_mbcs_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_mbcs_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_mbcs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1397,7 +1397,7 @@ static PyObject * _codecs_oem_encode_impl(PyObject *module, PyObject *str, const char *errors); static PyObject * -_codecs_oem_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_oem_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *str; @@ -1430,7 +1430,7 @@ _codecs_code_page_encode_impl(PyObject *module, int code_page, PyObject *str, const char *errors); static PyObject * -_codecs_code_page_encode(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_code_page_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int code_page; @@ -1467,7 +1467,7 @@ _codecs_register_error_impl(PyObject *module, const char *errors, PyObject *handler); static PyObject * -_codecs_register_error(PyObject *module, PyObject **args, Py_ssize_t nargs) +_codecs_register_error(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *errors; @@ -1536,4 +1536,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=894910ed4900eeae input=a9049054013a1b77]*/ +/*[clinic end generated code: output=06fa0d6803103c62 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cryptmodule.c.h b/Modules/clinic/_cryptmodule.c.h index 385612525e2..71eb53cd5e6 100644 --- a/Modules/clinic/_cryptmodule.c.h +++ b/Modules/clinic/_cryptmodule.c.h @@ -20,7 +20,7 @@ static PyObject * crypt_crypt_impl(PyObject *module, const char *word, const char *salt); static PyObject * -crypt_crypt(PyObject *module, PyObject **args, Py_ssize_t nargs) +crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *word; @@ -35,4 +35,4 @@ crypt_crypt(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=f5a6aff28d43154f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8d803e53466b1cd3 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_datetimemodule.c.h b/Modules/clinic/_datetimemodule.c.h index 3887bbadd4b..4d920495815 100644 --- a/Modules/clinic/_datetimemodule.c.h +++ b/Modules/clinic/_datetimemodule.c.h @@ -20,7 +20,7 @@ static PyObject * datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz); static PyObject * -datetime_datetime_now(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +datetime_datetime_now(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"tz", NULL}; @@ -36,4 +36,4 @@ datetime_datetime_now(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyO exit: return return_value; } -/*[clinic end generated code: output=93cb014e47dae4b3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1fc05897ab239b3f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h index c0e0b0b1890..63d5b1a41fb 100644 --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -52,7 +52,7 @@ _dbm_dbm_get_impl(dbmobject *self, const char *key, Py_ssize_clean_t key_length, PyObject *default_value); static PyObject * -_dbm_dbm_get(dbmobject *self, PyObject **args, Py_ssize_t nargs) +_dbm_dbm_get(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *key; @@ -86,7 +86,7 @@ _dbm_dbm_setdefault_impl(dbmobject *self, const char *key, PyObject *default_value); static PyObject * -_dbm_dbm_setdefault(dbmobject *self, PyObject **args, Py_ssize_t nargs) +_dbm_dbm_setdefault(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *key; @@ -125,7 +125,7 @@ dbmopen_impl(PyObject *module, const char *filename, const char *flags, int mode); static PyObject * -dbmopen(PyObject *module, PyObject **args, Py_ssize_t nargs) +dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *filename; @@ -141,4 +141,4 @@ dbmopen(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=627d28ce1f3188dc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8ce71abac849155f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index 9563afa88d0..6b558876dd0 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -161,7 +161,7 @@ _elementtree_Element_find_impl(ElementObject *self, PyObject *path, PyObject *namespaces); static PyObject * -_elementtree_Element_find(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_elementtree_Element_find(ElementObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "namespaces", NULL}; @@ -193,7 +193,7 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyObject *path, PyObject *namespaces); static PyObject * -_elementtree_Element_findtext(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_elementtree_Element_findtext(ElementObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "default", "namespaces", NULL}; @@ -225,7 +225,7 @@ _elementtree_Element_findall_impl(ElementObject *self, PyObject *path, PyObject *namespaces); static PyObject * -_elementtree_Element_findall(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_elementtree_Element_findall(ElementObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "namespaces", NULL}; @@ -256,7 +256,7 @@ _elementtree_Element_iterfind_impl(ElementObject *self, PyObject *path, PyObject *namespaces); static PyObject * -_elementtree_Element_iterfind(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_elementtree_Element_iterfind(ElementObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "namespaces", NULL}; @@ -287,7 +287,7 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, PyObject *default_value); static PyObject * -_elementtree_Element_get(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_elementtree_Element_get(ElementObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "default", NULL}; @@ -334,7 +334,7 @@ static PyObject * _elementtree_Element_iter_impl(ElementObject *self, PyObject *tag); static PyObject * -_elementtree_Element_iter(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_elementtree_Element_iter(ElementObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"tag", NULL}; @@ -363,7 +363,7 @@ static PyObject * _elementtree_Element_getiterator_impl(ElementObject *self, PyObject *tag); static PyObject * -_elementtree_Element_getiterator(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_elementtree_Element_getiterator(ElementObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"tag", NULL}; @@ -410,7 +410,7 @@ _elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index, PyObject *subelement); static PyObject * -_elementtree_Element_insert(ElementObject *self, PyObject **args, Py_ssize_t nargs) +_elementtree_Element_insert(ElementObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t index; @@ -473,7 +473,7 @@ _elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag, PyObject *attrib); static PyObject * -_elementtree_Element_makeelement(ElementObject *self, PyObject **args, Py_ssize_t nargs) +_elementtree_Element_makeelement(ElementObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *tag; @@ -529,7 +529,7 @@ _elementtree_Element_set_impl(ElementObject *self, PyObject *key, PyObject *value); static PyObject * -_elementtree_Element_set(ElementObject *self, PyObject **args, Py_ssize_t nargs) +_elementtree_Element_set(ElementObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *key; @@ -614,7 +614,7 @@ _elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag, PyObject *attrs); static PyObject * -_elementtree_TreeBuilder_start(TreeBuilderObject *self, PyObject **args, Py_ssize_t nargs) +_elementtree_TreeBuilder_start(TreeBuilderObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *tag; @@ -701,7 +701,7 @@ _elementtree_XMLParser_doctype_impl(XMLParserObject *self, PyObject *name, PyObject *pubid, PyObject *system); static PyObject * -_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject **args, Py_ssize_t nargs) +_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *name; @@ -733,7 +733,7 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self, PyObject *events_to_report); static PyObject * -_elementtree_XMLParser__setevents(XMLParserObject *self, PyObject **args, Py_ssize_t nargs) +_elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *events_queue; @@ -749,4 +749,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject **args, Py_ssi exit: return return_value; } -/*[clinic end generated code: output=ed55bd5209c12364 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c5a85a88bbb5cc06 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index 5178971399f..2222967aaa5 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -15,7 +15,7 @@ static PyObject * _gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value); static PyObject * -_gdbm_gdbm_get(dbmobject *self, PyObject **args, Py_ssize_t nargs) +_gdbm_gdbm_get(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *key; @@ -46,7 +46,7 @@ _gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key, PyObject *default_value); static PyObject * -_gdbm_gdbm_setdefault(dbmobject *self, PyObject **args, Py_ssize_t nargs) +_gdbm_gdbm_setdefault(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *key; @@ -237,7 +237,7 @@ static PyObject * dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode); static PyObject * -dbmopen(PyObject *module, PyObject **args, Py_ssize_t nargs) +dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *name; @@ -253,4 +253,4 @@ dbmopen(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=9c72502b30bb7485 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dc0aca8c00055d02 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index d34b71a068c..f08d7f3afd4 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -20,7 +20,7 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, long maxmem, long dklen); static PyObject * -_hashlib_scrypt(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"password", "salt", "n", "r", "p", "maxmem", "dklen", NULL}; @@ -57,4 +57,4 @@ _hashlib_scrypt(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *k #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=eda2a998d5b29030 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1ea7d0397f38e2c2 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h index a84db59460c..ed7eb5df052 100644 --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -88,7 +88,7 @@ _lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, Py_ssize_t max_length); static PyObject * -_lzma_LZMADecompressor_decompress(Decompressor *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_lzma_LZMADecompressor_decompress(Decompressor *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"data", "max_length", NULL}; @@ -236,7 +236,7 @@ _lzma__decode_filter_properties_impl(PyObject *module, lzma_vli filter_id, Py_buffer *encoded_props); static PyObject * -_lzma__decode_filter_properties(PyObject *module, PyObject **args, Py_ssize_t nargs) +_lzma__decode_filter_properties(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; lzma_vli filter_id; @@ -256,4 +256,4 @@ _lzma__decode_filter_properties(PyObject *module, PyObject **args, Py_ssize_t na return return_value; } -/*[clinic end generated code: output=d4e3802d0dea9af3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=38c2d52362bf3712 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_opcode.c.h b/Modules/clinic/_opcode.c.h index 2de8bd77d6a..4d593edfac0 100644 --- a/Modules/clinic/_opcode.c.h +++ b/Modules/clinic/_opcode.c.h @@ -15,7 +15,7 @@ static int _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg); static PyObject * -_opcode_stack_effect(PyObject *module, PyObject **args, Py_ssize_t nargs) +_opcode_stack_effect(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int opcode; @@ -35,4 +35,4 @@ _opcode_stack_effect(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=616105b05b55eb45 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=577a91c9aa5559a9 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_operator.c.h b/Modules/clinic/_operator.c.h index e6e2176e83a..9313f952454 100644 --- a/Modules/clinic/_operator.c.h +++ b/Modules/clinic/_operator.c.h @@ -43,7 +43,7 @@ static PyObject * _operator_add_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_add(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -73,7 +73,7 @@ static PyObject * _operator_sub_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_sub(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_sub(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -103,7 +103,7 @@ static PyObject * _operator_mul_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_mul(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -133,7 +133,7 @@ static PyObject * _operator_matmul_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_matmul(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_matmul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -163,7 +163,7 @@ static PyObject * _operator_floordiv_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_floordiv(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_floordiv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -193,7 +193,7 @@ static PyObject * _operator_truediv_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_truediv(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_truediv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -223,7 +223,7 @@ static PyObject * _operator_mod_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_mod(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_mod(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -298,7 +298,7 @@ static PyObject * _operator_lshift_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_lshift(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_lshift(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -328,7 +328,7 @@ static PyObject * _operator_rshift_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_rshift(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_rshift(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -386,7 +386,7 @@ static PyObject * _operator_and__impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_and_(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_and_(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -416,7 +416,7 @@ static PyObject * _operator_xor_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_xor(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_xor(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -446,7 +446,7 @@ static PyObject * _operator_or__impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_or_(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_or_(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -476,7 +476,7 @@ static PyObject * _operator_iadd_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_iadd(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_iadd(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -506,7 +506,7 @@ static PyObject * _operator_isub_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_isub(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_isub(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -536,7 +536,7 @@ static PyObject * _operator_imul_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_imul(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_imul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -566,7 +566,7 @@ static PyObject * _operator_imatmul_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_imatmul(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_imatmul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -596,7 +596,7 @@ static PyObject * _operator_ifloordiv_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_ifloordiv(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_ifloordiv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -626,7 +626,7 @@ static PyObject * _operator_itruediv_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_itruediv(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_itruediv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -656,7 +656,7 @@ static PyObject * _operator_imod_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_imod(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_imod(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -686,7 +686,7 @@ static PyObject * _operator_ilshift_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_ilshift(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_ilshift(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -716,7 +716,7 @@ static PyObject * _operator_irshift_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_irshift(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_irshift(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -746,7 +746,7 @@ static PyObject * _operator_iand_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_iand(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_iand(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -776,7 +776,7 @@ static PyObject * _operator_ixor_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_ixor(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_ixor(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -806,7 +806,7 @@ static PyObject * _operator_ior_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_ior(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_ior(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -836,7 +836,7 @@ static PyObject * _operator_concat_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_concat(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_concat(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -866,7 +866,7 @@ static PyObject * _operator_iconcat_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_iconcat(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_iconcat(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -896,7 +896,7 @@ static int _operator_contains_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_contains(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_contains(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -931,7 +931,7 @@ static Py_ssize_t _operator_indexOf_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_indexOf(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_indexOf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -966,7 +966,7 @@ static Py_ssize_t _operator_countOf_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_countOf(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_countOf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1001,7 +1001,7 @@ static PyObject * _operator_getitem_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_getitem(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_getitem(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1032,7 +1032,7 @@ _operator_setitem_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c); static PyObject * -_operator_setitem(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_setitem(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1063,7 +1063,7 @@ static PyObject * _operator_delitem_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_delitem(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_delitem(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1093,7 +1093,7 @@ static PyObject * _operator_eq_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_eq(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_eq(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1123,7 +1123,7 @@ static PyObject * _operator_ne_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_ne(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_ne(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1153,7 +1153,7 @@ static PyObject * _operator_lt_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_lt(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_lt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1183,7 +1183,7 @@ static PyObject * _operator_le_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_le(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_le(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1213,7 +1213,7 @@ static PyObject * _operator_gt_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_gt(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_gt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1243,7 +1243,7 @@ static PyObject * _operator_ge_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_ge(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_ge(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1273,7 +1273,7 @@ static PyObject * _operator_pow_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_pow(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1303,7 +1303,7 @@ static PyObject * _operator_ipow_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_ipow(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_ipow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1342,7 +1342,7 @@ static PyObject * _operator_is__impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_is_(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_is_(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1372,7 +1372,7 @@ static PyObject * _operator_is_not_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator_is_not(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_is_not(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1409,7 +1409,7 @@ _operator_length_hint_impl(PyObject *module, PyObject *obj, Py_ssize_t default_value); static PyObject * -_operator_length_hint(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator_length_hint(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *obj; @@ -1453,7 +1453,7 @@ static PyObject * _operator__compare_digest_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -_operator__compare_digest(PyObject *module, PyObject **args, Py_ssize_t nargs) +_operator__compare_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -1469,4 +1469,4 @@ _operator__compare_digest(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=7c42956af269cb21 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d840f7ea76af2372 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h index a0de46078b4..7fc00a00479 100644 --- a/Modules/clinic/_pickle.c.h +++ b/Modules/clinic/_pickle.c.h @@ -207,7 +207,7 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *global_name); static PyObject * -_pickle_Unpickler_find_class(UnpicklerObject *self, PyObject **args, Py_ssize_t nargs) +_pickle_Unpickler_find_class(UnpicklerObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *module_name; @@ -391,7 +391,7 @@ _pickle_dump_impl(PyObject *module, PyObject *obj, PyObject *file, PyObject *protocol, int fix_imports); static PyObject * -_pickle_dump(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_pickle_dump(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"obj", "file", "protocol", "fix_imports", NULL}; @@ -437,7 +437,7 @@ _pickle_dumps_impl(PyObject *module, PyObject *obj, PyObject *protocol, int fix_imports); static PyObject * -_pickle_dumps(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_pickle_dumps(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"obj", "protocol", "fix_imports", NULL}; @@ -493,7 +493,7 @@ _pickle_load_impl(PyObject *module, PyObject *file, int fix_imports, const char *encoding, const char *errors); static PyObject * -_pickle_load(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_pickle_load(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"file", "fix_imports", "encoding", "errors", NULL}; @@ -541,7 +541,7 @@ _pickle_loads_impl(PyObject *module, PyObject *data, int fix_imports, const char *encoding, const char *errors); static PyObject * -_pickle_loads(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"data", "fix_imports", "encoding", "errors", NULL}; @@ -560,4 +560,4 @@ _pickle_loads(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwn exit: return return_value; } -/*[clinic end generated code: output=a6243aaa6ea98732 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e995dd494045d876 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_sre.c.h b/Modules/clinic/_sre.c.h index 6eea0c8b252..2a7ca6bca1a 100644 --- a/Modules/clinic/_sre.c.h +++ b/Modules/clinic/_sre.c.h @@ -167,7 +167,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_match(PatternObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_match(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; @@ -200,7 +200,7 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_fullmatch(PatternObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_fullmatch(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; @@ -235,7 +235,7 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_search(PatternObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_search(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; @@ -268,7 +268,7 @@ _sre_SRE_Pattern_findall_impl(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_findall(PatternObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_findall(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; @@ -303,7 +303,7 @@ _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, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_finditer(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; @@ -335,7 +335,7 @@ _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, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_scanner(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; @@ -368,7 +368,7 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, Py_ssize_t maxsplit); static PyObject * -_sre_SRE_Pattern_split(PatternObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_split(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "maxsplit", NULL}; @@ -400,7 +400,7 @@ _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, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_sub(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"repl", "string", "count", NULL}; @@ -433,7 +433,7 @@ _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, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_subn(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"repl", "string", "count", NULL}; @@ -492,7 +492,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, PyObject *indexgroup); static PyObject * -_sre_compile(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"pattern", "flags", "code", "groups", "groupindex", "indexgroup", NULL}; @@ -527,7 +527,7 @@ static PyObject * _sre_SRE_Match_expand_impl(MatchObject *self, PyObject *template); static PyObject * -_sre_SRE_Match_expand(MatchObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Match_expand(MatchObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"template", NULL}; @@ -560,7 +560,7 @@ static PyObject * _sre_SRE_Match_groups_impl(MatchObject *self, PyObject *default_value); static PyObject * -_sre_SRE_Match_groups(MatchObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Match_groups(MatchObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"default", NULL}; @@ -593,7 +593,7 @@ static PyObject * _sre_SRE_Match_groupdict_impl(MatchObject *self, PyObject *default_value); static PyObject * -_sre_SRE_Match_groupdict(MatchObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Match_groupdict(MatchObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"default", NULL}; @@ -623,7 +623,7 @@ static Py_ssize_t _sre_SRE_Match_start_impl(MatchObject *self, PyObject *group); static PyObject * -_sre_SRE_Match_start(MatchObject *self, PyObject **args, Py_ssize_t nargs) +_sre_SRE_Match_start(MatchObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *group = NULL; @@ -657,7 +657,7 @@ static Py_ssize_t _sre_SRE_Match_end_impl(MatchObject *self, PyObject *group); static PyObject * -_sre_SRE_Match_end(MatchObject *self, PyObject **args, Py_ssize_t nargs) +_sre_SRE_Match_end(MatchObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *group = NULL; @@ -691,7 +691,7 @@ static PyObject * _sre_SRE_Match_span_impl(MatchObject *self, PyObject *group); static PyObject * -_sre_SRE_Match_span(MatchObject *self, PyObject **args, Py_ssize_t nargs) +_sre_SRE_Match_span(MatchObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *group = NULL; @@ -765,4 +765,4 @@ _sre_SRE_Scanner_search(ScannerObject *self, PyObject *Py_UNUSED(ignored)) { return _sre_SRE_Scanner_search_impl(self); } -/*[clinic end generated code: output=1e6a1be31302df09 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4b807104b65c1e0e input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 2427b5a42d3..32743e710f5 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -66,7 +66,7 @@ static PyObject * _ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode); static PyObject * -_ssl__SSLSocket_peer_certificate(PySSLSocket *self, PyObject **args, Py_ssize_t nargs) +_ssl__SSLSocket_peer_certificate(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int binary_mode = 0; @@ -476,7 +476,7 @@ _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, Py_ssize_t nargs, PyObject *kwnames) +_ssl__SSLContext_load_cert_chain(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"certfile", "keyfile", "password", NULL}; @@ -510,7 +510,7 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self, PyObject *cadata); static PyObject * -_ssl__SSLContext_load_verify_locations(PySSLContext *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_ssl__SSLContext_load_verify_locations(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"cafile", "capath", "cadata", NULL}; @@ -550,7 +550,7 @@ _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, Py_ssize_t nargs, PyObject *kwnames) +_ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sock", "server_side", "server_hostname", NULL}; @@ -584,7 +584,7 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PyObject *hostname_obj); static PyObject * -_ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", NULL}; @@ -706,7 +706,7 @@ static PyObject * _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form); static PyObject * -_ssl__SSLContext_get_ca_certs(PySSLContext *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_ssl__SSLContext_get_ca_certs(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"binary_form", NULL}; @@ -763,7 +763,7 @@ static PyObject * _ssl_MemoryBIO_read_impl(PySSLMemoryBIO *self, int len); static PyObject * -_ssl_MemoryBIO_read(PySSLMemoryBIO *self, PyObject **args, Py_ssize_t nargs) +_ssl_MemoryBIO_read(PySSLMemoryBIO *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int len = -1; @@ -848,7 +848,7 @@ static PyObject * _ssl_RAND_add_impl(PyObject *module, Py_buffer *view, double entropy); static PyObject * -_ssl_RAND_add(PyObject *module, PyObject **args, Py_ssize_t nargs) +_ssl_RAND_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer view = {NULL, NULL}; @@ -1017,7 +1017,7 @@ static PyObject * _ssl_txt2obj_impl(PyObject *module, const char *txt, int name); static PyObject * -_ssl_txt2obj(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_ssl_txt2obj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"txt", "name", NULL}; @@ -1083,7 +1083,7 @@ static PyObject * _ssl_enum_certificates_impl(PyObject *module, const char *store_name); static PyObject * -_ssl_enum_certificates(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_ssl_enum_certificates(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"store_name", NULL}; @@ -1122,7 +1122,7 @@ static PyObject * _ssl_enum_crls_impl(PyObject *module, const char *store_name); static PyObject * -_ssl_enum_crls(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"store_name", NULL}; @@ -1168,4 +1168,4 @@ _ssl_enum_crls(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kw #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=00790af9c3f31706 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3d42305ed0ad162a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index c273ee37046..6e43215b737 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -91,7 +91,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, Py_ssize_t offset); static PyObject * -Struct_unpack_from(PyStructObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +Struct_unpack_from(PyStructObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"buffer", "offset", NULL}; @@ -198,7 +198,7 @@ static PyObject * unpack_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer); static PyObject * -unpack(PyObject *module, PyObject **args, Py_ssize_t nargs) +unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyStructObject *s_object = NULL; @@ -239,7 +239,7 @@ unpack_from_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer, Py_ssize_t offset); static PyObject * -unpack_from(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +unpack_from(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "buffer", "offset", NULL}; @@ -284,7 +284,7 @@ iter_unpack_impl(PyObject *module, PyStructObject *s_object, PyObject *buffer); static PyObject * -iter_unpack(PyObject *module, PyObject **args, Py_ssize_t nargs) +iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyStructObject *s_object = NULL; @@ -302,4 +302,4 @@ iter_unpack(PyObject *module, PyObject **args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=fce060787b4c5261 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9119f213a951e4cc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_tkinter.c.h b/Modules/clinic/_tkinter.c.h index 6b8dabb0b56..a9dd73911b8 100644 --- a/Modules/clinic/_tkinter.c.h +++ b/Modules/clinic/_tkinter.c.h @@ -263,7 +263,7 @@ _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name, PyObject *func); static PyObject * -_tkinter_tkapp_createcommand(TkappObject *self, PyObject **args, Py_ssize_t nargs) +_tkinter_tkapp_createcommand(TkappObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *name; @@ -320,7 +320,7 @@ _tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file, int mask, PyObject *func); static PyObject * -_tkinter_tkapp_createfilehandler(TkappObject *self, PyObject **args, Py_ssize_t nargs) +_tkinter_tkapp_createfilehandler(TkappObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *file; @@ -381,7 +381,7 @@ _tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds, PyObject *func); static PyObject * -_tkinter_tkapp_createtimerhandler(TkappObject *self, PyObject **args, Py_ssize_t nargs) +_tkinter_tkapp_createtimerhandler(TkappObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int milliseconds; @@ -409,7 +409,7 @@ static PyObject * _tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold); static PyObject * -_tkinter_tkapp_mainloop(TkappObject *self, PyObject **args, Py_ssize_t nargs) +_tkinter_tkapp_mainloop(TkappObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int threshold = 0; @@ -436,7 +436,7 @@ static PyObject * _tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags); static PyObject * -_tkinter_tkapp_dooneevent(TkappObject *self, PyObject **args, Py_ssize_t nargs) +_tkinter_tkapp_dooneevent(TkappObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int flags = 0; @@ -552,7 +552,7 @@ _tkinter_create_impl(PyObject *module, const char *screenName, const char *use); static PyObject * -_tkinter_create(PyObject *module, PyObject **args, Py_ssize_t nargs) +_tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *screenName = NULL; @@ -638,4 +638,4 @@ _tkinter_getbusywaitinterval(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */ -/*[clinic end generated code: output=ca36236c57713ba0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eb3202e07db3dbb1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_tracemalloc.c.h b/Modules/clinic/_tracemalloc.c.h index 206dea748be..2ad39707207 100644 --- a/Modules/clinic/_tracemalloc.c.h +++ b/Modules/clinic/_tracemalloc.c.h @@ -90,7 +90,7 @@ static PyObject * _tracemalloc_start_impl(PyObject *module, int nframe); static PyObject * -_tracemalloc_start(PyObject *module, PyObject **args, Py_ssize_t nargs) +_tracemalloc_start(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int nframe = 1; @@ -185,4 +185,4 @@ _tracemalloc_get_traced_memory(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _tracemalloc_get_traced_memory_impl(module); } -/*[clinic end generated code: output=db4f909464c186e2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d98afded69c89d52 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_weakref.c.h b/Modules/clinic/_weakref.c.h index 97e2a24ba07..1c3aea13ef8 100644 --- a/Modules/clinic/_weakref.c.h +++ b/Modules/clinic/_weakref.c.h @@ -44,7 +44,7 @@ _weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct, PyObject *key); static PyObject * -_weakref__remove_dead_weakref(PyObject *module, PyObject **args, Py_ssize_t nargs) +_weakref__remove_dead_weakref(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *dct; @@ -59,4 +59,4 @@ _weakref__remove_dead_weakref(PyObject *module, PyObject **args, Py_ssize_t narg exit: return return_value; } -/*[clinic end generated code: output=87ddb70850080222 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b6a61a4f365a3f0a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h index e5781efb938..80edbf58a20 100644 --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -102,7 +102,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle, int use_overlapped); static PyObject * -_winapi_ConnectNamedPipe(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_winapi_ConnectNamedPipe(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"handle", "overlapped", NULL}; @@ -138,7 +138,7 @@ _winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name, DWORD flags_and_attributes, HANDLE template_file); static PyObject * -_winapi_CreateFile(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_CreateFile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; LPCTSTR file_name; @@ -180,7 +180,7 @@ _winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path, LPWSTR dst_path); static PyObject * -_winapi_CreateJunction(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_CreateJunction(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; LPWSTR src_path; @@ -214,7 +214,7 @@ _winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode, LPSECURITY_ATTRIBUTES security_attributes); static PyObject * -_winapi_CreateNamedPipe(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_CreateNamedPipe(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; LPCTSTR name; @@ -262,7 +262,7 @@ static PyObject * _winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size); static PyObject * -_winapi_CreatePipe(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_CreatePipe(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *pipe_attrs; @@ -306,7 +306,7 @@ _winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, PyObject *startup_info); static PyObject * -_winapi_CreateProcess(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_CreateProcess(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_UNICODE *application_name; @@ -352,7 +352,7 @@ _winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle, DWORD options); static PyObject * -_winapi_DuplicateHandle(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_DuplicateHandle(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE source_process_handle; @@ -611,7 +611,7 @@ _winapi_OpenProcess_impl(PyObject *module, DWORD desired_access, BOOL inherit_handle, DWORD process_id); static PyObject * -_winapi_OpenProcess(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_OpenProcess(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; DWORD desired_access; @@ -648,7 +648,7 @@ static PyObject * _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size); static PyObject * -_winapi_PeekNamedPipe(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_PeekNamedPipe(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE handle; @@ -677,7 +677,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, int size, int use_overlapped); static PyObject * -_winapi_ReadFile(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_winapi_ReadFile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"handle", "size", "overlapped", NULL}; @@ -712,7 +712,7 @@ _winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe, PyObject *collect_data_timeout); static PyObject * -_winapi_SetNamedPipeHandleState(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_SetNamedPipeHandleState(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE named_pipe; @@ -744,7 +744,7 @@ _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle, UINT exit_code); static PyObject * -_winapi_TerminateProcess(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_TerminateProcess(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE handle; @@ -772,7 +772,7 @@ static PyObject * _winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout); static PyObject * -_winapi_WaitNamedPipe(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_WaitNamedPipe(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; LPCTSTR name; @@ -802,7 +802,7 @@ _winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq, BOOL wait_flag, DWORD milliseconds); static PyObject * -_winapi_WaitForMultipleObjects(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_WaitForMultipleObjects(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *handle_seq; @@ -837,7 +837,7 @@ _winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle, DWORD milliseconds); static PyObject * -_winapi_WaitForSingleObject(PyObject *module, PyObject **args, Py_ssize_t nargs) +_winapi_WaitForSingleObject(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE handle; @@ -871,7 +871,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer, int use_overlapped); static PyObject * -_winapi_WriteFile(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_winapi_WriteFile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"handle", "buffer", "overlapped", NULL}; @@ -907,4 +907,4 @@ _winapi_GetACP(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _winapi_GetACP_impl(module); } -/*[clinic end generated code: output=fd91c1ec286f0bf3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b9c00c323c9f4944 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index 2b611951ea5..b03a507914a 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -71,7 +71,7 @@ static PyObject * array_array_pop_impl(arrayobject *self, Py_ssize_t i); static PyObject * -array_array_pop(arrayobject *self, PyObject **args, Py_ssize_t nargs) +array_array_pop(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t i = -1; @@ -108,7 +108,7 @@ static PyObject * array_array_insert_impl(arrayobject *self, Py_ssize_t i, PyObject *v); static PyObject * -array_array_insert(arrayobject *self, PyObject **args, Py_ssize_t nargs) +array_array_insert(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t i; @@ -206,7 +206,7 @@ static PyObject * array_array_fromfile_impl(arrayobject *self, PyObject *f, Py_ssize_t n); static PyObject * -array_array_fromfile(arrayobject *self, PyObject **args, Py_ssize_t nargs) +array_array_fromfile(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *f; @@ -452,7 +452,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, PyObject *items); static PyObject * -array__array_reconstructor(PyObject *module, PyObject **args, Py_ssize_t nargs) +array__array_reconstructor(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyTypeObject *arraytype; @@ -505,4 +505,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=c7dfe61312b236a9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1289bde2a095a712 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h index 2a2811b6f08..cc8d818e1d8 100644 --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -16,7 +16,7 @@ audioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width, Py_ssize_t index); static PyObject * -audioop_getsample(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_getsample(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -51,7 +51,7 @@ static PyObject * audioop_max_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_max(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -85,7 +85,7 @@ static PyObject * audioop_minmax_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_minmax(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_minmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -119,7 +119,7 @@ static PyObject * audioop_avg_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_avg(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_avg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -153,7 +153,7 @@ static PyObject * audioop_rms_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_rms(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_rms(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -188,7 +188,7 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment, Py_buffer *reference); static PyObject * -audioop_findfit(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_findfit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -227,7 +227,7 @@ audioop_findfactor_impl(PyObject *module, Py_buffer *fragment, Py_buffer *reference); static PyObject * -audioop_findfactor(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_findfactor(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -266,7 +266,7 @@ audioop_findmax_impl(PyObject *module, Py_buffer *fragment, Py_ssize_t length); static PyObject * -audioop_findmax(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_findmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -300,7 +300,7 @@ static PyObject * audioop_avgpp_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_avgpp(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_avgpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -334,7 +334,7 @@ static PyObject * audioop_maxpp_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_maxpp(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_maxpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -368,7 +368,7 @@ static PyObject * audioop_cross_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_cross(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_cross(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -403,7 +403,7 @@ audioop_mul_impl(PyObject *module, Py_buffer *fragment, int width, double factor); static PyObject * -audioop_mul(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -439,7 +439,7 @@ audioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width, double lfactor, double rfactor); static PyObject * -audioop_tomono(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_tomono(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -476,7 +476,7 @@ audioop_tostereo_impl(PyObject *module, Py_buffer *fragment, int width, double lfactor, double rfactor); static PyObject * -audioop_tostereo(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_tostereo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -513,7 +513,7 @@ audioop_add_impl(PyObject *module, Py_buffer *fragment1, Py_buffer *fragment2, int width); static PyObject * -audioop_add(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment1 = {NULL, NULL}; @@ -552,7 +552,7 @@ static PyObject * audioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias); static PyObject * -audioop_bias(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_bias(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -587,7 +587,7 @@ static PyObject * audioop_reverse_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_reverse(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_reverse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -621,7 +621,7 @@ static PyObject * audioop_byteswap_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_byteswap(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_byteswap(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -656,7 +656,7 @@ audioop_lin2lin_impl(PyObject *module, Py_buffer *fragment, int width, int newwidth); static PyObject * -audioop_lin2lin(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_lin2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -694,7 +694,7 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width, int weightA, int weightB); static PyObject * -audioop_ratecv(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_ratecv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -734,7 +734,7 @@ static PyObject * audioop_lin2ulaw_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_lin2ulaw(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_lin2ulaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -768,7 +768,7 @@ static PyObject * audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_ulaw2lin(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_ulaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -802,7 +802,7 @@ static PyObject * audioop_lin2alaw_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_lin2alaw(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_lin2alaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -836,7 +836,7 @@ static PyObject * audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width); static PyObject * -audioop_alaw2lin(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_alaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -871,7 +871,7 @@ audioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width, PyObject *state); static PyObject * -audioop_lin2adpcm(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_lin2adpcm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -907,7 +907,7 @@ audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width, PyObject *state); static PyObject * -audioop_adpcm2lin(PyObject *module, PyObject **args, Py_ssize_t nargs) +audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer fragment = {NULL, NULL}; @@ -928,4 +928,4 @@ audioop_adpcm2lin(PyObject *module, PyObject **args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=e2076026235d7f0f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2f88b8827ee0aa9b input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index 138991f96c0..8099cbd4cce 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -46,7 +46,7 @@ static PyObject * binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick); static PyObject * -binascii_b2a_uu(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +binascii_b2a_uu(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "backtick", NULL}; @@ -113,7 +113,7 @@ static PyObject * binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int newline); static PyObject * -binascii_b2a_base64(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "newline", NULL}; @@ -276,7 +276,7 @@ static unsigned int binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc); static PyObject * -binascii_crc_hqx(PyObject *module, PyObject **args, Py_ssize_t nargs) +binascii_crc_hqx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -315,7 +315,7 @@ static unsigned int binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc); static PyObject * -binascii_crc32(PyObject *module, PyObject **args, Py_ssize_t nargs) +binascii_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -490,7 +490,7 @@ static PyObject * binascii_a2b_qp_impl(PyObject *module, Py_buffer *data, int header); static PyObject * -binascii_a2b_qp(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +binascii_a2b_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"data", "header", NULL}; @@ -530,7 +530,7 @@ binascii_b2a_qp_impl(PyObject *module, Py_buffer *data, int quotetabs, int istext, int header); static PyObject * -binascii_b2a_qp(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"data", "quotetabs", "istext", "header", NULL}; @@ -554,4 +554,4 @@ binascii_b2a_qp(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *k return return_value; } -/*[clinic end generated code: output=2878727c0cf4f636 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=815f1c453fd6568f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h index a65c6ef31ab..9b3c62eeb7a 100644 --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -647,7 +647,7 @@ static PyObject * cmath_log_impl(PyObject *module, Py_complex x, PyObject *y_obj); static PyObject * -cmath_log(PyObject *module, PyObject **args, Py_ssize_t nargs) +cmath_log(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_complex x; @@ -732,7 +732,7 @@ static PyObject * cmath_rect_impl(PyObject *module, double r, double phi); static PyObject * -cmath_rect(PyObject *module, PyObject **args, Py_ssize_t nargs) +cmath_rect(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; double r; @@ -858,7 +858,7 @@ cmath_isclose_impl(PyObject *module, Py_complex a, Py_complex b, double rel_tol, double abs_tol); static PyObject * -cmath_isclose(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; @@ -882,4 +882,4 @@ cmath_isclose(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwn exit: return return_value; } -/*[clinic end generated code: output=51ba28d27d10264e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dd93c3a6aeb42ebb input=a9049054013a1b77]*/ diff --git a/Modules/clinic/fcntlmodule.c.h b/Modules/clinic/fcntlmodule.c.h index 874a129fc43..f61c526a958 100644 --- a/Modules/clinic/fcntlmodule.c.h +++ b/Modules/clinic/fcntlmodule.c.h @@ -25,7 +25,7 @@ static PyObject * fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg); static PyObject * -fcntl_fcntl(PyObject *module, PyObject **args, Py_ssize_t nargs) +fcntl_fcntl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -83,7 +83,7 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code, PyObject *ob_arg, int mutate_arg); static PyObject * -fcntl_ioctl(PyObject *module, PyObject **args, Py_ssize_t nargs) +fcntl_ioctl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -117,7 +117,7 @@ static PyObject * fcntl_flock_impl(PyObject *module, int fd, int code); static PyObject * -fcntl_flock(PyObject *module, PyObject **args, Py_ssize_t nargs) +fcntl_flock(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -168,7 +168,7 @@ fcntl_lockf_impl(PyObject *module, int fd, int code, PyObject *lenobj, PyObject *startobj, int whence); static PyObject * -fcntl_lockf(PyObject *module, PyObject **args, Py_ssize_t nargs) +fcntl_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -186,4 +186,4 @@ fcntl_lockf(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=6105e3ada306f434 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2f6e70ae67ec8ac9 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/gcmodule.c.h b/Modules/clinic/gcmodule.c.h index c31ef65eb06..c431af79efd 100644 --- a/Modules/clinic/gcmodule.c.h +++ b/Modules/clinic/gcmodule.c.h @@ -85,7 +85,7 @@ static Py_ssize_t gc_collect_impl(PyObject *module, int generation); static PyObject * -gc_collect(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +gc_collect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"generation", NULL}; @@ -325,4 +325,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=4f41ec4588154f2b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6f9ee4d8dd1f36c1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/grpmodule.c.h b/Modules/clinic/grpmodule.c.h index 0bf32344749..bb51b8a53ab 100644 --- a/Modules/clinic/grpmodule.c.h +++ b/Modules/clinic/grpmodule.c.h @@ -17,7 +17,7 @@ static PyObject * grp_getgrgid_impl(PyObject *module, PyObject *id); static PyObject * -grp_getgrgid(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +grp_getgrgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"id", NULL}; @@ -49,7 +49,7 @@ static PyObject * grp_getgrnam_impl(PyObject *module, PyObject *name); static PyObject * -grp_getgrnam(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +grp_getgrnam(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"name", NULL}; @@ -86,4 +86,4 @@ grp_getgrall(PyObject *module, PyObject *Py_UNUSED(ignored)) { return grp_getgrall_impl(module); } -/*[clinic end generated code: output=e7ef2cbc437eedcb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0ccba09e8ec14c81 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index 9ce443f03ef..ffebb079183 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -15,7 +15,7 @@ static PyObject * math_gcd_impl(PyObject *module, PyObject *a, PyObject *b); static PyObject * -math_gcd(PyObject *module, PyObject **args, Py_ssize_t nargs) +math_gcd(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *a; @@ -132,7 +132,7 @@ static PyObject * math_ldexp_impl(PyObject *module, double x, PyObject *i); static PyObject * -math_ldexp(PyObject *module, PyObject **args, Py_ssize_t nargs) +math_ldexp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; double x; @@ -253,7 +253,7 @@ static PyObject * math_fmod_impl(PyObject *module, double x, double y); static PyObject * -math_fmod(PyObject *module, PyObject **args, Py_ssize_t nargs) +math_fmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; double x; @@ -282,7 +282,7 @@ static PyObject * math_hypot_impl(PyObject *module, double x, double y); static PyObject * -math_hypot(PyObject *module, PyObject **args, Py_ssize_t nargs) +math_hypot(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; double x; @@ -311,7 +311,7 @@ static PyObject * math_pow_impl(PyObject *module, double x, double y); static PyObject * -math_pow(PyObject *module, PyObject **args, Py_ssize_t nargs) +math_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; double x; @@ -492,7 +492,7 @@ math_isclose_impl(PyObject *module, double a, double b, double rel_tol, double abs_tol); static PyObject * -math_isclose(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +math_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; @@ -516,4 +516,4 @@ math_isclose(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwna exit: return return_value; } -/*[clinic end generated code: output=d9bfbd645d273209 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e554bad553045546 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h index 3c0a19b6561..850d76bace7 100644 --- a/Modules/clinic/md5module.c.h +++ b/Modules/clinic/md5module.c.h @@ -78,7 +78,7 @@ static PyObject * _md5_md5_impl(PyObject *module, PyObject *string); static PyObject * -_md5_md5(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", NULL}; @@ -94,4 +94,4 @@ _md5_md5(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) exit: return return_value; } -/*[clinic end generated code: output=3139ae340ad1ea4e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=50a95670913de8fb input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 85ba7b58391..9decf7a8d24 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -34,7 +34,7 @@ static PyObject * os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks); static PyObject * -os_stat(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "dir_fd", "follow_symlinks", NULL}; @@ -72,7 +72,7 @@ static PyObject * os_lstat_impl(PyObject *module, path_t *path, int dir_fd); static PyObject * -os_lstat(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "dir_fd", NULL}; @@ -133,7 +133,7 @@ os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks); static PyObject * -os_access(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; @@ -240,7 +240,7 @@ static PyObject * os_chdir_impl(PyObject *module, path_t *path); static PyObject * -os_chdir(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -278,7 +278,7 @@ static PyObject * os_fchdir_impl(PyObject *module, int fd); static PyObject * -os_fchdir(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_fchdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", NULL}; @@ -331,7 +331,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, int follow_symlinks); static PyObject * -os_chmod(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL}; @@ -371,7 +371,7 @@ static PyObject * os_fchmod_impl(PyObject *module, int fd, int mode); static PyObject * -os_fchmod(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", "mode", NULL}; @@ -409,7 +409,7 @@ static PyObject * os_lchmod_impl(PyObject *module, path_t *path, int mode); static PyObject * -os_lchmod(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "mode", NULL}; @@ -454,7 +454,7 @@ os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, int follow_symlinks); static PyObject * -os_chflags(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "flags", "follow_symlinks", NULL}; @@ -496,7 +496,7 @@ static PyObject * os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags); static PyObject * -os_lchflags(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "flags", NULL}; @@ -534,7 +534,7 @@ static PyObject * os_chroot_impl(PyObject *module, path_t *path); static PyObject * -os_chroot(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -571,7 +571,7 @@ static PyObject * os_fsync_impl(PyObject *module, int fd); static PyObject * -os_fsync(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_fsync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", NULL}; @@ -627,7 +627,7 @@ static PyObject * os_fdatasync_impl(PyObject *module, int fd); static PyObject * -os_fdatasync(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_fdatasync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", NULL}; @@ -686,7 +686,7 @@ os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks); static PyObject * -os_chown(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL}; @@ -729,7 +729,7 @@ static PyObject * os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid); static PyObject * -os_fchown(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_fchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", "uid", "gid", NULL}; @@ -768,7 +768,7 @@ static PyObject * os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid); static PyObject * -os_lchown(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "uid", "gid", NULL}; @@ -855,7 +855,7 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks); static PyObject * -os_link(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL}; @@ -907,7 +907,7 @@ static PyObject * os_listdir_impl(PyObject *module, path_t *path); static PyObject * -os_listdir(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -1040,7 +1040,7 @@ static PyObject * os__getvolumepathname_impl(PyObject *module, PyObject *path); static PyObject * -os__getvolumepathname(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -1079,7 +1079,7 @@ static PyObject * os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd); static PyObject * -os_mkdir(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; @@ -1147,7 +1147,7 @@ static PyObject * os_getpriority_impl(PyObject *module, int which, int who); static PyObject * -os_getpriority(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_getpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"which", "who", NULL}; @@ -1182,7 +1182,7 @@ static PyObject * os_setpriority_impl(PyObject *module, int which, int who, int priority); static PyObject * -os_setpriority(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_setpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"which", "who", "priority", NULL}; @@ -1223,7 +1223,7 @@ os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd); static PyObject * -os_rename(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; @@ -1268,7 +1268,7 @@ os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd); static PyObject * -os_replace(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; @@ -1311,7 +1311,7 @@ static PyObject * os_rmdir_impl(PyObject *module, path_t *path, int dir_fd); static PyObject * -os_rmdir(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "dir_fd", NULL}; @@ -1347,7 +1347,7 @@ static long os_system_impl(PyObject *module, Py_UNICODE *command); static PyObject * -os_system(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"command", NULL}; @@ -1386,7 +1386,7 @@ static long os_system_impl(PyObject *module, PyObject *command); static PyObject * -os_system(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"command", NULL}; @@ -1458,7 +1458,7 @@ static PyObject * os_unlink_impl(PyObject *module, path_t *path, int dir_fd); static PyObject * -os_unlink(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "dir_fd", NULL}; @@ -1497,7 +1497,7 @@ static PyObject * os_remove_impl(PyObject *module, path_t *path, int dir_fd); static PyObject * -os_remove(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "dir_fd", NULL}; @@ -1580,7 +1580,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks); static PyObject * -os_utime(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL}; @@ -1617,7 +1617,7 @@ static PyObject * os__exit_impl(PyObject *module, int status); static PyObject * -os__exit(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os__exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -1654,7 +1654,7 @@ static PyObject * os_execv_impl(PyObject *module, path_t *path, PyObject *argv); static PyObject * -os_execv(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0); @@ -1697,7 +1697,7 @@ static PyObject * os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env); static PyObject * -os_execve(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "argv", "env", NULL}; @@ -1743,7 +1743,7 @@ static PyObject * os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv); static PyObject * -os_spawnv(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; @@ -1790,7 +1790,7 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, PyObject *env); static PyObject * -os_spawnve(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; @@ -1840,7 +1840,7 @@ os_register_at_fork_impl(PyObject *module, PyObject *before, PyObject *after_in_child, PyObject *after_in_parent); static PyObject * -os_register_at_fork(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_register_at_fork(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"before", "after_in_child", "after_in_parent", NULL}; @@ -1924,7 +1924,7 @@ static PyObject * os_sched_get_priority_max_impl(PyObject *module, int policy); static PyObject * -os_sched_get_priority_max(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_sched_get_priority_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"policy", NULL}; @@ -1958,7 +1958,7 @@ static PyObject * os_sched_get_priority_min_impl(PyObject *module, int policy); static PyObject * -os_sched_get_priority_min(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_sched_get_priority_min(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"policy", NULL}; @@ -2063,7 +2063,7 @@ os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, struct sched_param *param); static PyObject * -os_sched_setscheduler(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_sched_setscheduler(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pid; @@ -2135,7 +2135,7 @@ os_sched_setparam_impl(PyObject *module, pid_t pid, struct sched_param *param); static PyObject * -os_sched_setparam(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_sched_setparam(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pid; @@ -2230,7 +2230,7 @@ static PyObject * os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask); static PyObject * -os_sched_setaffinity(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_sched_setaffinity(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pid; @@ -2458,7 +2458,7 @@ static PyObject * os_getpgid_impl(PyObject *module, pid_t pid); static PyObject * -os_getpgid(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_getpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"pid", NULL}; @@ -2605,7 +2605,7 @@ static PyObject * os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal); static PyObject * -os_kill(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pid; @@ -2638,7 +2638,7 @@ static PyObject * os_killpg_impl(PyObject *module, pid_t pgid, int signal); static PyObject * -os_killpg(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_killpg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pgid; @@ -2795,7 +2795,7 @@ static PyObject * os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid); static PyObject * -os_setreuid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_setreuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; uid_t ruid; @@ -2828,7 +2828,7 @@ static PyObject * os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid); static PyObject * -os_setregid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_setregid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; gid_t rgid; @@ -2908,7 +2908,7 @@ static PyObject * os_wait3_impl(PyObject *module, int options); static PyObject * -os_wait3(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_wait3(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"options", NULL}; @@ -2945,7 +2945,7 @@ static PyObject * os_wait4_impl(PyObject *module, pid_t pid, int options); static PyObject * -os_wait4(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_wait4(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"pid", "options", NULL}; @@ -2991,7 +2991,7 @@ static PyObject * os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options); static PyObject * -os_waitid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_waitid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; idtype_t idtype; @@ -3030,7 +3030,7 @@ static PyObject * os_waitpid_impl(PyObject *module, pid_t pid, int options); static PyObject * -os_waitpid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pid; @@ -3068,7 +3068,7 @@ static PyObject * os_waitpid_impl(PyObject *module, intptr_t pid, int options); static PyObject * -os_waitpid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; intptr_t pid; @@ -3137,7 +3137,7 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd); static PyObject * -os_symlink(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL}; @@ -3258,7 +3258,7 @@ static PyObject * os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp); static PyObject * -os_setpgid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_setpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pid; @@ -3322,7 +3322,7 @@ static PyObject * os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid); static PyObject * -os_tcsetpgrp(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_tcsetpgrp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3358,7 +3358,7 @@ static int os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd); static PyObject * -os_open(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; @@ -3399,7 +3399,7 @@ static PyObject * os_close_impl(PyObject *module, int fd); static PyObject * -os_close(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_close(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", NULL}; @@ -3429,7 +3429,7 @@ static PyObject * os_closerange_impl(PyObject *module, int fd_low, int fd_high); static PyObject * -os_closerange(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_closerange(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd_low; @@ -3490,7 +3490,7 @@ static PyObject * os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable); static PyObject * -os_dup2(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", "fd2", "inheritable", NULL}; @@ -3531,7 +3531,7 @@ static PyObject * os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length); static PyObject * -os_lockf(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3566,7 +3566,7 @@ static Py_off_t os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how); static PyObject * -os_lseek(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3601,7 +3601,7 @@ static PyObject * os_read_impl(PyObject *module, int fd, Py_ssize_t length); static PyObject * -os_read(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3640,7 +3640,7 @@ static Py_ssize_t os_readv_impl(PyObject *module, int fd, PyObject *buffers); static PyObject * -os_readv(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_readv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3681,7 +3681,7 @@ static PyObject * os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset); static PyObject * -os_pread(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_pread(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3713,7 +3713,7 @@ static Py_ssize_t os_write_impl(PyObject *module, int fd, Py_buffer *data); static PyObject * -os_write(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3755,7 +3755,7 @@ static PyObject * os_fstat_impl(PyObject *module, int fd); static PyObject * -os_fstat(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_fstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", NULL}; @@ -3887,7 +3887,7 @@ static Py_ssize_t os_writev_impl(PyObject *module, int fd, PyObject *buffers); static PyObject * -os_writev(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_writev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3929,7 +3929,7 @@ static Py_ssize_t os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset); static PyObject * -os_pwrite(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -3978,7 +3978,7 @@ static PyObject * os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd); static PyObject * -os_mkfifo(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; @@ -4030,7 +4030,7 @@ os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, int dir_fd); static PyObject * -os_mknod(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "mode", "device", "dir_fd", NULL}; @@ -4142,7 +4142,7 @@ static dev_t os_makedev_impl(PyObject *module, int major, int minor); static PyObject * -os_makedev(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_makedev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int major; @@ -4180,7 +4180,7 @@ static PyObject * os_ftruncate_impl(PyObject *module, int fd, Py_off_t length); static PyObject * -os_ftruncate(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_ftruncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -4216,7 +4216,7 @@ static PyObject * os_truncate_impl(PyObject *module, path_t *path, Py_off_t length); static PyObject * -os_truncate(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "length", NULL}; @@ -4258,7 +4258,7 @@ os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length); static PyObject * -os_posix_fallocate(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -4301,7 +4301,7 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length, int advice); static PyObject * -os_posix_fadvise(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -4336,7 +4336,7 @@ static PyObject * os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); static PyObject * -os_putenv(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *name; @@ -4369,7 +4369,7 @@ static PyObject * os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); static PyObject * -os_putenv(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *name = NULL; @@ -4507,7 +4507,7 @@ static int os_WIFCONTINUED_impl(PyObject *module, int status); static PyObject * -os_WIFCONTINUED(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_WIFCONTINUED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -4546,7 +4546,7 @@ static int os_WIFSTOPPED_impl(PyObject *module, int status); static PyObject * -os_WIFSTOPPED(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_WIFSTOPPED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -4585,7 +4585,7 @@ static int os_WIFSIGNALED_impl(PyObject *module, int status); static PyObject * -os_WIFSIGNALED(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_WIFSIGNALED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -4624,7 +4624,7 @@ static int os_WIFEXITED_impl(PyObject *module, int status); static PyObject * -os_WIFEXITED(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_WIFEXITED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -4663,7 +4663,7 @@ static int os_WEXITSTATUS_impl(PyObject *module, int status); static PyObject * -os_WEXITSTATUS(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_WEXITSTATUS(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -4702,7 +4702,7 @@ static int os_WTERMSIG_impl(PyObject *module, int status); static PyObject * -os_WTERMSIG(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_WTERMSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -4741,7 +4741,7 @@ static int os_WSTOPSIG_impl(PyObject *module, int status); static PyObject * -os_WSTOPSIG(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_WSTOPSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"status", NULL}; @@ -4817,7 +4817,7 @@ static PyObject * os_statvfs_impl(PyObject *module, path_t *path); static PyObject * -os_statvfs(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -4854,7 +4854,7 @@ static PyObject * os__getdiskusage_impl(PyObject *module, Py_UNICODE *path); static PyObject * -os__getdiskusage(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -4890,7 +4890,7 @@ static long os_fpathconf_impl(PyObject *module, int fd, int name); static PyObject * -os_fpathconf(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_fpathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -4932,7 +4932,7 @@ static long os_pathconf_impl(PyObject *module, path_t *path, int name); static PyObject * -os_pathconf(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "name", NULL}; @@ -5080,7 +5080,7 @@ static PyObject * os_startfile_impl(PyObject *module, path_t *filepath, Py_UNICODE *operation); static PyObject * -os_startfile(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"filepath", "operation", NULL}; @@ -5145,7 +5145,7 @@ static PyObject * os_device_encoding_impl(PyObject *module, int fd); static PyObject * -os_device_encoding(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_device_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"fd", NULL}; @@ -5177,7 +5177,7 @@ static PyObject * os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid); static PyObject * -os_setresuid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_setresuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; uid_t ruid; @@ -5211,7 +5211,7 @@ static PyObject * os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid); static PyObject * -os_setresgid(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_setresgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; gid_t rgid; @@ -5295,7 +5295,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks); static PyObject * -os_getxattr(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; @@ -5343,7 +5343,7 @@ os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks); static PyObject * -os_setxattr(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL}; @@ -5396,7 +5396,7 @@ os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks); static PyObject * -os_removexattr(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; @@ -5443,7 +5443,7 @@ static PyObject * os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks); static PyObject * -os_listxattr(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", "follow_symlinks", NULL}; @@ -5560,7 +5560,7 @@ static PyObject * os_set_inheritable_impl(PyObject *module, int fd, int inheritable); static PyObject * -os_set_inheritable(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_set_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -5628,7 +5628,7 @@ os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, int inheritable); static PyObject * -os_set_handle_inheritable(PyObject *module, PyObject **args, Py_ssize_t nargs) +os_set_handle_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; intptr_t handle; @@ -5687,7 +5687,7 @@ static PyObject * os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks); static PyObject * -os_DirEntry_stat(DirEntry *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_DirEntry_stat(DirEntry *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"follow_symlinks", NULL}; @@ -5717,7 +5717,7 @@ static int os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks); static PyObject * -os_DirEntry_is_dir(DirEntry *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_DirEntry_is_dir(DirEntry *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"follow_symlinks", NULL}; @@ -5752,7 +5752,7 @@ static int os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks); static PyObject * -os_DirEntry_is_file(DirEntry *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_DirEntry_is_file(DirEntry *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"follow_symlinks", NULL}; @@ -5829,7 +5829,7 @@ static PyObject * os_scandir_impl(PyObject *module, path_t *path); static PyObject * -os_scandir(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -5866,7 +5866,7 @@ static PyObject * os_fspath_impl(PyObject *module, PyObject *path); static PyObject * -os_fspath(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_fspath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; @@ -5898,7 +5898,7 @@ static PyObject * os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags); static PyObject * -os_getrandom(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"size", "flags", NULL}; @@ -6405,4 +6405,4 @@ os_getrandom(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwna #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=949867cb46218339 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b6ade5f170d5a431 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h index 9b9d6e0296b..777b6f31145 100644 --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -18,7 +18,7 @@ pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, int isfinal); static PyObject * -pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject **args, Py_ssize_t nargs) +pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *data; @@ -124,7 +124,7 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, const char *encoding); static PyObject * -pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject **args, Py_ssize_t nargs) +pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *context; @@ -191,7 +191,7 @@ static PyObject * pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag); static PyObject * -pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyObject **args, Py_ssize_t nargs) +pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int flag = 1; @@ -240,7 +240,7 @@ pyexpat_ParserCreate_impl(PyObject *module, const char *encoding, const char *namespace_separator, PyObject *intern); static PyObject * -pyexpat_ParserCreate(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +pyexpat_ParserCreate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"encoding", "namespace_separator", "intern", NULL}; @@ -289,4 +289,4 @@ pyexpat_ErrorString(PyObject *module, PyObject *arg) #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=5d2e355f2b48e6c3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=34d02345deee104c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/resource.c.h b/Modules/clinic/resource.c.h index cb8451261ee..9163cac76c6 100644 --- a/Modules/clinic/resource.c.h +++ b/Modules/clinic/resource.c.h @@ -66,7 +66,7 @@ static PyObject * resource_setrlimit_impl(PyObject *module, int resource, PyObject *limits); static PyObject * -resource_setrlimit(PyObject *module, PyObject **args, Py_ssize_t nargs) +resource_setrlimit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int resource; @@ -157,4 +157,4 @@ resource_getpagesize(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef RESOURCE_PRLIMIT_METHODDEF #define RESOURCE_PRLIMIT_METHODDEF #endif /* !defined(RESOURCE_PRLIMIT_METHODDEF) */ -/*[clinic end generated code: output=d7dabf49ce5b767f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2a69aca90631a582 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h index f3b92a401d1..be29355e23f 100644 --- a/Modules/clinic/sha1module.c.h +++ b/Modules/clinic/sha1module.c.h @@ -78,7 +78,7 @@ static PyObject * _sha1_sha1_impl(PyObject *module, PyObject *string); static PyObject * -_sha1_sha1(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", NULL}; @@ -94,4 +94,4 @@ _sha1_sha1(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwname exit: return return_value; } -/*[clinic end generated code: output=594cf600d6ba4776 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9ee2aec7bb2b9e72 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha256module.c.h b/Modules/clinic/sha256module.c.h index 2c981685c5c..9de5bd087d9 100644 --- a/Modules/clinic/sha256module.c.h +++ b/Modules/clinic/sha256module.c.h @@ -78,7 +78,7 @@ static PyObject * _sha256_sha256_impl(PyObject *module, PyObject *string); static PyObject * -_sha256_sha256(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sha256_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", NULL}; @@ -108,7 +108,7 @@ static PyObject * _sha256_sha224_impl(PyObject *module, PyObject *string); static PyObject * -_sha256_sha224(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sha256_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", NULL}; @@ -124,4 +124,4 @@ _sha256_sha224(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kw exit: return return_value; } -/*[clinic end generated code: output=84e7b8365b3ca4d3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4b90199bc9f7cc88 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha512module.c.h b/Modules/clinic/sha512module.c.h index 09cd3fe2800..ebb510e39a6 100644 --- a/Modules/clinic/sha512module.c.h +++ b/Modules/clinic/sha512module.c.h @@ -78,7 +78,7 @@ static PyObject * _sha512_sha512_impl(PyObject *module, PyObject *string); static PyObject * -_sha512_sha512(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sha512_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", NULL}; @@ -108,7 +108,7 @@ static PyObject * _sha512_sha384_impl(PyObject *module, PyObject *string); static PyObject * -_sha512_sha384(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_sha512_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", NULL}; @@ -124,4 +124,4 @@ _sha512_sha384(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kw exit: return return_value; } -/*[clinic end generated code: output=2f6ad0831d16c35f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f963a543bf3c72e8 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index cc3e64002bc..dc3aadf878b 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -80,7 +80,7 @@ static PyObject * signal_signal_impl(PyObject *module, int signalnum, PyObject *handler); static PyObject * -signal_signal(PyObject *module, PyObject **args, Py_ssize_t nargs) +signal_signal(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int signalnum; @@ -147,7 +147,7 @@ static PyObject * signal_siginterrupt_impl(PyObject *module, int signalnum, int flag); static PyObject * -signal_siginterrupt(PyObject *module, PyObject **args, Py_ssize_t nargs) +signal_siginterrupt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int signalnum; @@ -186,7 +186,7 @@ signal_setitimer_impl(PyObject *module, int which, PyObject *seconds, PyObject *interval); static PyObject * -signal_setitimer(PyObject *module, PyObject **args, Py_ssize_t nargs) +signal_setitimer(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int which; @@ -251,7 +251,7 @@ static PyObject * signal_pthread_sigmask_impl(PyObject *module, int how, PyObject *mask); static PyObject * -signal_pthread_sigmask(PyObject *module, PyObject **args, Py_ssize_t nargs) +signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int how; @@ -344,7 +344,7 @@ signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, PyObject *timeout_obj); static PyObject * -signal_sigtimedwait(PyObject *module, PyObject **args, Py_ssize_t nargs) +signal_sigtimedwait(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *sigset; @@ -379,7 +379,7 @@ signal_pthread_kill_impl(PyObject *module, unsigned long thread_id, int signalnum); static PyObject * -signal_pthread_kill(PyObject *module, PyObject **args, Py_ssize_t nargs) +signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; unsigned long thread_id; @@ -440,4 +440,4 @@ signal_pthread_kill(PyObject *module, PyObject **args, Py_ssize_t nargs) #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=a003d3fea9a33daa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=36132f4189381fe0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/symtablemodule.c.h b/Modules/clinic/symtablemodule.c.h index 22dfc0bd272..6f1e4fe0c73 100644 --- a/Modules/clinic/symtablemodule.c.h +++ b/Modules/clinic/symtablemodule.c.h @@ -16,7 +16,7 @@ _symtable_symtable_impl(PyObject *module, const char *str, PyObject *filename, const char *startstr); static PyObject * -_symtable_symtable(PyObject *module, PyObject **args, Py_ssize_t nargs) +_symtable_symtable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *str; @@ -32,4 +32,4 @@ _symtable_symtable(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=ef379e514fde8477 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c18565060a6cae04 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h index 52226d64b35..72e3f654577 100644 --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -20,7 +20,7 @@ unicodedata_UCD_decimal_impl(PyObject *self, int chr, PyObject *default_value); static PyObject * -unicodedata_UCD_decimal(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicodedata_UCD_decimal(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int chr; @@ -53,7 +53,7 @@ static PyObject * unicodedata_UCD_digit_impl(PyObject *self, int chr, PyObject *default_value); static PyObject * -unicodedata_UCD_digit(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicodedata_UCD_digit(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int chr; @@ -87,7 +87,7 @@ unicodedata_UCD_numeric_impl(PyObject *self, int chr, PyObject *default_value); static PyObject * -unicodedata_UCD_numeric(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicodedata_UCD_numeric(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int chr; @@ -300,7 +300,7 @@ unicodedata_UCD_normalize_impl(PyObject *self, const char *form, PyObject *input); static PyObject * -unicodedata_UCD_normalize(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicodedata_UCD_normalize(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *form; @@ -332,7 +332,7 @@ static PyObject * unicodedata_UCD_name_impl(PyObject *self, int chr, PyObject *default_value); static PyObject * -unicodedata_UCD_name(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicodedata_UCD_name(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int chr; @@ -379,4 +379,4 @@ unicodedata_UCD_lookup(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=7ec9a3c8fbfd3c3a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dc899bff0ecd14c1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zipimport.c.h b/Modules/clinic/zipimport.c.h index b24838d73b7..548aade6efa 100644 --- a/Modules/clinic/zipimport.c.h +++ b/Modules/clinic/zipimport.c.h @@ -65,7 +65,7 @@ zipimport_zipimporter_find_module_impl(ZipImporter *self, PyObject *fullname, PyObject *path); static PyObject * -zipimport_zipimporter_find_module(ZipImporter *self, PyObject **args, Py_ssize_t nargs) +zipimport_zipimporter_find_module(ZipImporter *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *fullname; @@ -101,7 +101,7 @@ zipimport_zipimporter_find_loader_impl(ZipImporter *self, PyObject *fullname, PyObject *path); static PyObject * -zipimport_zipimporter_find_loader(ZipImporter *self, PyObject **args, Py_ssize_t nargs) +zipimport_zipimporter_find_loader(ZipImporter *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *fullname; @@ -291,4 +291,4 @@ zipimport_zipimporter_get_source(ZipImporter *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=bac6c9144950eaec input=a9049054013a1b77]*/ +/*[clinic end generated code: output=93cb62a3a9752b9f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h index 33c767236bb..c68c4a10785 100644 --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -20,7 +20,7 @@ static PyObject * zlib_compress_impl(PyObject *module, Py_buffer *data, int level); static PyObject * -zlib_compress(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +zlib_compress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "level", NULL}; @@ -64,7 +64,7 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, Py_ssize_t bufsize); static PyObject * -zlib_decompress(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +zlib_decompress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "wbits", "bufsize", NULL}; @@ -126,7 +126,7 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict); static PyObject * -zlib_compressobj(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"level", "method", "wbits", "memLevel", "strategy", "zdict", NULL}; @@ -172,7 +172,7 @@ static PyObject * zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict); static PyObject * -zlib_decompressobj(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +zlib_decompressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"wbits", "zdict", NULL}; @@ -254,7 +254,7 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, Py_ssize_t max_length); static PyObject * -zlib_Decompress_decompress(compobject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +zlib_Decompress_decompress(compobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "max_length", NULL}; @@ -296,7 +296,7 @@ static PyObject * zlib_Compress_flush_impl(compobject *self, int mode); static PyObject * -zlib_Compress_flush(compobject *self, PyObject **args, Py_ssize_t nargs) +zlib_Compress_flush(compobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode = Z_FINISH; @@ -371,7 +371,7 @@ static PyObject * zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length); static PyObject * -zlib_Decompress_flush(compobject *self, PyObject **args, Py_ssize_t nargs) +zlib_Decompress_flush(compobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t length = DEF_BUF_SIZE; @@ -404,7 +404,7 @@ static PyObject * zlib_adler32_impl(PyObject *module, Py_buffer *data, unsigned int value); static PyObject * -zlib_adler32(PyObject *module, PyObject **args, Py_ssize_t nargs) +zlib_adler32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -443,7 +443,7 @@ static PyObject * zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value); static PyObject * -zlib_crc32(PyObject *module, PyObject **args, Py_ssize_t nargs) +zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; @@ -471,4 +471,4 @@ zlib_crc32(PyObject *module, PyObject **args, Py_ssize_t nargs) #ifndef ZLIB_DECOMPRESS_COPY_METHODDEF #define ZLIB_DECOMPRESS_COPY_METHODDEF #endif /* !defined(ZLIB_DECOMPRESS_COPY_METHODDEF) */ -/*[clinic end generated code: output=6378d429f0819817 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=43dd29b8977765f9 input=a9049054013a1b77]*/ diff --git a/Objects/call.c b/Objects/call.c index 7b46dbc822e..b53a98c76b0 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -81,7 +81,7 @@ _Py_CheckFunctionResult(PyObject *callable, PyObject *result, const char *where) /* --- Core PyObject call functions ------------------------------- */ PyObject * -_PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, +_PyObject_FastCallDict(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs) { /* _PyObject_FastCallDict() must not be called with an exception set, @@ -134,7 +134,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, PyObject * -_PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t nargs, +_PyObject_FastCallKeywords(PyObject *callable, PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames) { /* _PyObject_FastCallKeywords() must not be called with an exception set, @@ -254,7 +254,7 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) /* --- PyFunction call functions ---------------------------------- */ static PyObject* _Py_HOT_FUNCTION -function_code_fastcall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs, +function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs, PyObject *globals) { PyFrameObject *f; @@ -296,7 +296,7 @@ function_code_fastcall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs, PyObject * -_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, +_PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); @@ -383,7 +383,7 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, } PyObject * -_PyFunction_FastCallKeywords(PyObject *func, PyObject **stack, +_PyFunction_FastCallKeywords(PyObject *func, PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); @@ -443,8 +443,9 @@ _PyFunction_FastCallKeywords(PyObject *func, PyObject **stack, /* --- PyCFunction call functions --------------------------------- */ PyObject * -_PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **args, - Py_ssize_t nargs, PyObject *kwargs) +_PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs) { /* _PyMethodDef_RawFastCallDict() must not be called with an exception set, because it can clear it (directly or indirectly) and so the @@ -532,7 +533,7 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg case METH_FASTCALL | METH_KEYWORDS: { - PyObject **stack; + PyObject *const *stack; PyObject *kwnames; _PyCFunctionFastWithKeywords fastmeth = (_PyCFunctionFastWithKeywords)meth; @@ -542,7 +543,7 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg result = (*fastmeth) (self, stack, nargs, kwnames); if (stack != args) { - PyMem_Free(stack); + PyMem_Free((PyObject **)stack); } Py_XDECREF(kwnames); break; @@ -569,7 +570,8 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg PyObject * -_PyCFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, +_PyCFunction_FastCallDict(PyObject *func, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs) { PyObject *result; @@ -586,8 +588,9 @@ _PyCFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject * -_PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject **args, - Py_ssize_t nargs, PyObject *kwnames) +_PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwnames) { /* _PyMethodDef_RawFastCallKeywords() must not be called with an exception set, because it can clear it (directly or indirectly) and so the @@ -715,8 +718,9 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject * PyObject * -_PyCFunction_FastCallKeywords(PyObject *func, PyObject **args, - Py_ssize_t nargs, PyObject *kwnames) +_PyCFunction_FastCallKeywords(PyObject *func, + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwnames) { PyObject *result; @@ -834,8 +838,8 @@ PyObject_CallObject(PyObject *callable, PyObject *args) /* Positional arguments are obj followed by args: call callable(obj, *args, **kwargs) */ PyObject * -_PyObject_FastCall_Prepend(PyObject *callable, - PyObject *obj, PyObject **args, Py_ssize_t nargs) +_PyObject_FastCall_Prepend(PyObject *callable, PyObject *obj, + PyObject *const *args, Py_ssize_t nargs) { PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **args2; @@ -1268,7 +1272,7 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...) /* Issue #29234: Inlining _PyStack_AsTuple() into callers increases their stack consumption, Disable inlining to optimize the stack consumption. */ PyObject* _Py_NO_INLINE -_PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs) +_PyStack_AsTuple(PyObject *const *stack, Py_ssize_t nargs) { PyObject *args; Py_ssize_t i; @@ -1288,7 +1292,7 @@ _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs) PyObject* -_PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs, +_PyStack_AsTupleSlice(PyObject *const *stack, Py_ssize_t nargs, Py_ssize_t start, Py_ssize_t end) { PyObject *args; @@ -1313,7 +1317,7 @@ _PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs, PyObject * -_PyStack_AsDict(PyObject **values, PyObject *kwnames) +_PyStack_AsDict(PyObject *const *values, PyObject *kwnames) { Py_ssize_t nkwargs; PyObject *kwdict; @@ -1340,8 +1344,8 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames) int -_PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, - PyObject ***p_stack, PyObject **p_kwnames) +_PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, + PyObject *const **p_stack, PyObject **p_kwnames) { PyObject **stack, **kwstack; Py_ssize_t nkwargs; diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index d45592be559..d88883245ef 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -58,7 +58,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, PyObject *deletechars); static PyObject * -bytearray_translate(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytearray_translate(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "delete", NULL}; @@ -94,7 +94,7 @@ static PyObject * bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to); static PyObject * -bytearray_maketrans(void *null, PyObject **args, Py_ssize_t nargs) +bytearray_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer frm = {NULL, NULL}; @@ -140,7 +140,7 @@ bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * -bytearray_replace(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs) +bytearray_replace(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer old = {NULL, NULL}; @@ -188,7 +188,7 @@ bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit); static PyObject * -bytearray_split(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytearray_split(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sep", "maxsplit", NULL}; @@ -263,7 +263,7 @@ bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit); static PyObject * -bytearray_rsplit(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytearray_rsplit(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sep", "maxsplit", NULL}; @@ -317,7 +317,7 @@ static PyObject * bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item); static PyObject * -bytearray_insert(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs) +bytearray_insert(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t index; @@ -394,7 +394,7 @@ static PyObject * bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index); static PyObject * -bytearray_pop(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs) +bytearray_pop(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t index = -1; @@ -454,7 +454,7 @@ static PyObject * bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes); static PyObject * -bytearray_strip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs) +bytearray_strip(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *bytes = Py_None; @@ -485,7 +485,7 @@ static PyObject * bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes); static PyObject * -bytearray_lstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs) +bytearray_lstrip(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *bytes = Py_None; @@ -516,7 +516,7 @@ static PyObject * bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes); static PyObject * -bytearray_rstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs) +bytearray_rstrip(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *bytes = Py_None; @@ -555,7 +555,7 @@ bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, const char *errors); static PyObject * -bytearray_decode(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytearray_decode(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"encoding", "errors", NULL}; @@ -602,7 +602,7 @@ static PyObject * bytearray_splitlines_impl(PyByteArrayObject *self, int keepends); static PyObject * -bytearray_splitlines(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytearray_splitlines(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"keepends", NULL}; @@ -680,7 +680,7 @@ static PyObject * bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto); static PyObject * -bytearray_reduce_ex(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs) +bytearray_reduce_ex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int proto = 0; @@ -712,4 +712,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=c2804d009182328c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bb9051a369adb328 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 9c358b54e33..c781948ead0 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -23,7 +23,7 @@ static PyObject * bytes_split_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit); static PyObject * -bytes_split(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytes_split(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sep", "maxsplit", NULL}; @@ -142,7 +142,7 @@ static PyObject * bytes_rsplit_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit); static PyObject * -bytes_rsplit(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytes_rsplit(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sep", "maxsplit", NULL}; @@ -190,7 +190,7 @@ static PyObject * bytes_strip_impl(PyBytesObject *self, PyObject *bytes); static PyObject * -bytes_strip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs) +bytes_strip(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *bytes = Py_None; @@ -221,7 +221,7 @@ static PyObject * bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes); static PyObject * -bytes_lstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs) +bytes_lstrip(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *bytes = Py_None; @@ -252,7 +252,7 @@ static PyObject * bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes); static PyObject * -bytes_rstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs) +bytes_rstrip(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *bytes = Py_None; @@ -288,7 +288,7 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, PyObject *deletechars); static PyObject * -bytes_translate(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytes_translate(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "delete", NULL}; @@ -324,7 +324,7 @@ static PyObject * bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to); static PyObject * -bytes_maketrans(void *null, PyObject **args, Py_ssize_t nargs) +bytes_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer frm = {NULL, NULL}; @@ -370,7 +370,7 @@ bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * -bytes_replace(PyBytesObject *self, PyObject **args, Py_ssize_t nargs) +bytes_replace(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer old = {NULL, NULL}; @@ -419,7 +419,7 @@ bytes_decode_impl(PyBytesObject *self, const char *encoding, const char *errors); static PyObject * -bytes_decode(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytes_decode(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"encoding", "errors", NULL}; @@ -453,7 +453,7 @@ static PyObject * bytes_splitlines_impl(PyBytesObject *self, int keepends); static PyObject * -bytes_splitlines(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +bytes_splitlines(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"keepends", NULL}; @@ -499,4 +499,4 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=fc9e02359cc56d36 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=470acd12b2534765 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/dictobject.c.h b/Objects/clinic/dictobject.c.h index 538d52e7630..58677cd772b 100644 --- a/Objects/clinic/dictobject.c.h +++ b/Objects/clinic/dictobject.c.h @@ -15,7 +15,7 @@ static PyObject * dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value); static PyObject * -dict_fromkeys(PyTypeObject *type, PyObject **args, Py_ssize_t nargs) +dict_fromkeys(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *iterable; @@ -54,7 +54,7 @@ static PyObject * dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value); static PyObject * -dict_get(PyDictObject *self, PyObject **args, Py_ssize_t nargs) +dict_get(PyDictObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *key; @@ -87,7 +87,7 @@ dict_setdefault_impl(PyDictObject *self, PyObject *key, PyObject *default_value); static PyObject * -dict_setdefault(PyDictObject *self, PyObject **args, Py_ssize_t nargs) +dict_setdefault(PyDictObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *key; @@ -103,4 +103,4 @@ dict_setdefault(PyDictObject *self, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=8d09902e60b7ab02 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d7508c5091609a23 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 9325154233b..ac3ff0c9f83 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -53,7 +53,7 @@ static PyObject * float___round___impl(PyObject *self, PyObject *o_ndigits); static PyObject * -float___round__(PyObject *self, PyObject **args, Py_ssize_t nargs) +float___round__(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *o_ndigits = NULL; @@ -263,7 +263,7 @@ float___set_format___impl(PyTypeObject *type, const char *typestr, const char *fmt); static PyObject * -float___set_format__(PyTypeObject *type, PyObject **args, Py_ssize_t nargs) +float___set_format__(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; const char *typestr; @@ -305,4 +305,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=90c06ea9d72130cc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a3c366a156be61f9 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h index d22ce22e03b..63da672ca3d 100644 --- a/Objects/clinic/listobject.c.h +++ b/Objects/clinic/listobject.c.h @@ -15,7 +15,7 @@ static PyObject * list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object); static PyObject * -list_insert(PyListObject *self, PyObject **args, Py_ssize_t nargs) +list_insert(PyListObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t index; @@ -100,7 +100,7 @@ static PyObject * list_pop_impl(PyListObject *self, Py_ssize_t index); static PyObject * -list_pop(PyListObject *self, PyObject **args, Py_ssize_t nargs) +list_pop(PyListObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t index = -1; @@ -128,7 +128,7 @@ static PyObject * list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse); static PyObject * -list_sort(PyListObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +list_sort(PyListObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "reverse", NULL}; @@ -180,7 +180,7 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start, Py_ssize_t stop); static PyObject * -list_index(PyListObject *self, PyObject **args, Py_ssize_t nargs) +list_index(PyListObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *value; @@ -285,4 +285,4 @@ list___reversed__(PyListObject *self, PyObject *Py_UNUSED(ignored)) { return list___reversed___impl(self); } -/*[clinic end generated code: output=4a4f72a5e7ff5068 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d8cb29e6e6d79844 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h index 1b706d65d2e..14f5515c7a6 100644 --- a/Objects/clinic/longobject.c.h +++ b/Objects/clinic/longobject.c.h @@ -146,7 +146,7 @@ int_to_bytes_impl(PyObject *self, Py_ssize_t length, PyObject *byteorder, int is_signed); static PyObject * -int_to_bytes(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +int_to_bytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"length", "byteorder", "signed", NULL}; @@ -193,7 +193,7 @@ int_from_bytes_impl(PyTypeObject *type, PyObject *bytes_obj, PyObject *byteorder, int is_signed); static PyObject * -int_from_bytes(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +int_from_bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"bytes", "byteorder", "signed", NULL}; @@ -211,4 +211,4 @@ int_from_bytes(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject * exit: return return_value; } -/*[clinic end generated code: output=c9adfdc329651cc4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fd64beb83bd16df3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/odictobject.c.h b/Objects/clinic/odictobject.c.h index 6c1cb91277a..15a8bece037 100644 --- a/Objects/clinic/odictobject.c.h +++ b/Objects/clinic/odictobject.c.h @@ -15,7 +15,7 @@ static PyObject * OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value); static PyObject * -OrderedDict_fromkeys(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +OrderedDict_fromkeys(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"iterable", "value", NULL}; @@ -49,7 +49,7 @@ OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key, PyObject *default_value); static PyObject * -OrderedDict_setdefault(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +OrderedDict_setdefault(PyODictObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "default", NULL}; @@ -82,7 +82,7 @@ static PyObject * OrderedDict_popitem_impl(PyODictObject *self, int last); static PyObject * -OrderedDict_popitem(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +OrderedDict_popitem(PyODictObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"last", NULL}; @@ -114,7 +114,7 @@ static PyObject * OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last); static PyObject * -OrderedDict_move_to_end(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +OrderedDict_move_to_end(PyODictObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "last", NULL}; @@ -131,4 +131,4 @@ OrderedDict_move_to_end(PyODictObject *self, PyObject **args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=b2f82eca6e8c8084 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7f23d569eda2a558 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/tupleobject.c.h b/Objects/clinic/tupleobject.c.h index c453e5872bf..bef900515b5 100644 --- a/Objects/clinic/tupleobject.c.h +++ b/Objects/clinic/tupleobject.c.h @@ -18,7 +18,7 @@ tuple_index_impl(PyTupleObject *self, PyObject *value, Py_ssize_t start, Py_ssize_t stop); static PyObject * -tuple_index(PyTupleObject *self, PyObject **args, Py_ssize_t nargs) +tuple_index(PyTupleObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *value; @@ -95,4 +95,4 @@ tuple___getnewargs__(PyTupleObject *self, PyObject *Py_UNUSED(ignored)) { return tuple___getnewargs___impl(self); } -/*[clinic end generated code: output=d24a9893b3a740c6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0fbf4321fb4365ac input=a9049054013a1b77]*/ diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h index 09365277af1..643ef0491b3 100644 --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -77,7 +77,7 @@ static PyObject * unicode_center_impl(PyObject *self, Py_ssize_t width, Py_UCS4 fillchar); static PyObject * -unicode_center(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicode_center(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t width; @@ -115,7 +115,7 @@ static PyObject * unicode_encode_impl(PyObject *self, const char *encoding, const char *errors); static PyObject * -unicode_encode(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +unicode_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"encoding", "errors", NULL}; @@ -148,7 +148,7 @@ static PyObject * unicode_expandtabs_impl(PyObject *self, int tabsize); static PyObject * -unicode_expandtabs(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +unicode_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"tabsize", NULL}; @@ -425,7 +425,7 @@ static PyObject * unicode_ljust_impl(PyObject *self, Py_ssize_t width, Py_UCS4 fillchar); static PyObject * -unicode_ljust(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicode_ljust(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t width; @@ -474,7 +474,7 @@ static PyObject * unicode_strip_impl(PyObject *self, PyObject *chars); static PyObject * -unicode_strip(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicode_strip(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *chars = Py_None; @@ -505,7 +505,7 @@ static PyObject * unicode_lstrip_impl(PyObject *self, PyObject *chars); static PyObject * -unicode_lstrip(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicode_lstrip(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *chars = NULL; @@ -536,7 +536,7 @@ static PyObject * unicode_rstrip_impl(PyObject *self, PyObject *chars); static PyObject * -unicode_rstrip(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicode_rstrip(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *chars = NULL; @@ -573,7 +573,7 @@ unicode_replace_impl(PyObject *self, PyObject *old, PyObject *new, Py_ssize_t count); static PyObject * -unicode_replace(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *old; @@ -605,7 +605,7 @@ static PyObject * unicode_rjust_impl(PyObject *self, Py_ssize_t width, Py_UCS4 fillchar); static PyObject * -unicode_rjust(PyObject *self, PyObject **args, Py_ssize_t nargs) +unicode_rjust(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_ssize_t width; @@ -642,7 +642,7 @@ static PyObject * unicode_split_impl(PyObject *self, PyObject *sep, Py_ssize_t maxsplit); static PyObject * -unicode_split(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +unicode_split(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sep", "maxsplit", NULL}; @@ -715,7 +715,7 @@ static PyObject * unicode_rsplit_impl(PyObject *self, PyObject *sep, Py_ssize_t maxsplit); static PyObject * -unicode_rsplit(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +unicode_rsplit(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sep", "maxsplit", NULL}; @@ -749,7 +749,7 @@ static PyObject * unicode_splitlines_impl(PyObject *self, int keepends); static PyObject * -unicode_splitlines(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +unicode_splitlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"keepends", NULL}; @@ -805,7 +805,7 @@ static PyObject * unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z); static PyObject * -unicode_maketrans(void *null, PyObject **args, Py_ssize_t nargs) +unicode_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *x; @@ -930,4 +930,4 @@ unicode_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return unicode_sizeof_impl(self); } -/*[clinic end generated code: output=816292e81a8a732e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1ad4e81b68194264 input=a9049054013a1b77]*/ diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 71d522433a2..a2530184cd3 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -256,7 +256,7 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs) // same to methoddescr_call(), but use FASTCALL convention. PyObject * _PyMethodDescr_FastCallKeywords(PyObject *descrobj, - PyObject **args, Py_ssize_t nargs, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { assert(Py_TYPE(descrobj) == &PyMethodDescr_Type); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5403ecb04f9..aa907018859 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3298,7 +3298,7 @@ type___subclasses___impl(PyTypeObject *self) } static PyObject * -type_prepare(PyObject *self, PyObject **args, Py_ssize_t nargs, +type_prepare(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { return PyDict_New(); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index c7480a0d87c..c8600a89413 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9835,7 +9835,7 @@ PyUnicode_Join(PyObject *separator, PyObject *seq) } PyObject * -_PyUnicode_JoinArray(PyObject *separator, PyObject **items, Py_ssize_t seqlen) +_PyUnicode_JoinArray(PyObject *separator, PyObject *const *items, Py_ssize_t seqlen) { PyObject *res = NULL; /* the result */ PyObject *sep = NULL; diff --git a/PC/clinic/_testconsole.c.h b/PC/clinic/_testconsole.c.h index e512fb172d7..8112e789ff6 100644 --- a/PC/clinic/_testconsole.c.h +++ b/PC/clinic/_testconsole.c.h @@ -18,7 +18,7 @@ _testconsole_write_input_impl(PyObject *module, PyObject *file, PyBytesObject *s); static PyObject * -_testconsole_write_input(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_testconsole_write_input(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"file", "s", NULL}; @@ -53,7 +53,7 @@ static PyObject * _testconsole_read_output_impl(PyObject *module, PyObject *file); static PyObject * -_testconsole_read_output(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"file", NULL}; @@ -79,4 +79,4 @@ _testconsole_read_output(PyObject *module, PyObject **args, Py_ssize_t nargs, Py #ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF #define _TESTCONSOLE_READ_OUTPUT_METHODDEF #endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */ -/*[clinic end generated code: output=ac80ed19e6edc0af input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e7dd05a60463c5f0 input=a9049054013a1b77]*/ diff --git a/PC/clinic/msvcrtmodule.c.h b/PC/clinic/msvcrtmodule.c.h index 6d7648a101d..22ddfea8024 100644 --- a/PC/clinic/msvcrtmodule.c.h +++ b/PC/clinic/msvcrtmodule.c.h @@ -43,7 +43,7 @@ static PyObject * msvcrt_locking_impl(PyObject *module, int fd, int mode, long nbytes); static PyObject * -msvcrt_locking(PyObject *module, PyObject **args, Py_ssize_t nargs) +msvcrt_locking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -78,7 +78,7 @@ static long msvcrt_setmode_impl(PyObject *module, int fd, int flags); static PyObject * -msvcrt_setmode(PyObject *module, PyObject **args, Py_ssize_t nargs) +msvcrt_setmode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int fd; @@ -116,7 +116,7 @@ static long msvcrt_open_osfhandle_impl(PyObject *module, void *handle, int flags); static PyObject * -msvcrt_open_osfhandle(PyObject *module, PyObject **args, Py_ssize_t nargs) +msvcrt_open_osfhandle(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; void *handle; @@ -430,7 +430,7 @@ static void * msvcrt_CrtSetReportFile_impl(PyObject *module, int type, void *file); static PyObject * -msvcrt_CrtSetReportFile(PyObject *module, PyObject **args, Py_ssize_t nargs) +msvcrt_CrtSetReportFile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int type; @@ -470,7 +470,7 @@ static long msvcrt_CrtSetReportMode_impl(PyObject *module, int type, int mode); static PyObject * -msvcrt_CrtSetReportMode(PyObject *module, PyObject **args, Py_ssize_t nargs) +msvcrt_CrtSetReportMode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int type; @@ -569,4 +569,4 @@ msvcrt_SetErrorMode(PyObject *module, PyObject *arg) #ifndef MSVCRT_SET_ERROR_MODE_METHODDEF #define MSVCRT_SET_ERROR_MODE_METHODDEF #endif /* !defined(MSVCRT_SET_ERROR_MODE_METHODDEF) */ -/*[clinic end generated code: output=66787cb934b8a3c2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3dd4cf62afb9771a input=a9049054013a1b77]*/ diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h index 4a1387323d4..69781a96928 100644 --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -84,7 +84,7 @@ winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback); static PyObject * -winreg_HKEYType___exit__(PyHKEYObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winreg_HKEYType___exit__(PyHKEYObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"exc_type", "exc_value", "traceback", NULL}; @@ -141,7 +141,7 @@ winreg_ConnectRegistry_impl(PyObject *module, Py_UNICODE *computer_name, HKEY key); static PyObject * -winreg_ConnectRegistry(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_ConnectRegistry(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_UNICODE *computer_name; @@ -188,7 +188,7 @@ static HKEY winreg_CreateKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key); static PyObject * -winreg_CreateKey(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_CreateKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -242,7 +242,7 @@ winreg_CreateKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); static PyObject * -winreg_CreateKeyEx(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; @@ -292,7 +292,7 @@ static PyObject * winreg_DeleteKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key); static PyObject * -winreg_DeleteKey(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_DeleteKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -341,7 +341,7 @@ winreg_DeleteKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, REGSAM access, int reserved); static PyObject * -winreg_DeleteKeyEx(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winreg_DeleteKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "sub_key", "access", "reserved", NULL}; @@ -379,7 +379,7 @@ static PyObject * winreg_DeleteValue_impl(PyObject *module, HKEY key, Py_UNICODE *value); static PyObject * -winreg_DeleteValue(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_DeleteValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -417,7 +417,7 @@ static PyObject * winreg_EnumKey_impl(PyObject *module, HKEY key, int index); static PyObject * -winreg_EnumKey(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_EnumKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -464,7 +464,7 @@ static PyObject * winreg_EnumValue_impl(PyObject *module, HKEY key, int index); static PyObject * -winreg_EnumValue(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_EnumValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -583,7 +583,7 @@ winreg_LoadKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, Py_UNICODE *file_name); static PyObject * -winreg_LoadKey(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_LoadKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -627,7 +627,7 @@ winreg_OpenKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); static PyObject * -winreg_OpenKey(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; @@ -679,7 +679,7 @@ winreg_OpenKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); static PyObject * -winreg_OpenKeyEx(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; @@ -767,7 +767,7 @@ static PyObject * winreg_QueryValue_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key); static PyObject * -winreg_QueryValue(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_QueryValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -806,7 +806,7 @@ static PyObject * winreg_QueryValueEx_impl(PyObject *module, HKEY key, Py_UNICODE *name); static PyObject * -winreg_QueryValueEx(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_QueryValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -850,7 +850,7 @@ static PyObject * winreg_SaveKey_impl(PyObject *module, HKEY key, Py_UNICODE *file_name); static PyObject * -winreg_SaveKey(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_SaveKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -901,7 +901,7 @@ winreg_SetValue_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, Py_ssize_clean_t value_length); static PyObject * -winreg_SetValue(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_SetValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -971,7 +971,7 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key, Py_UNICODE *value_name, PyObject *reserved, DWORD type, PyObject *value); static PyObject * -winreg_SetValueEx(PyObject *module, PyObject **args, Py_ssize_t nargs) +winreg_SetValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; @@ -1091,4 +1091,4 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=9f7991a8580bbd93 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d1c8e2678015dd7d input=a9049054013a1b77]*/ diff --git a/PC/clinic/winsound.c.h b/PC/clinic/winsound.c.h index c786aba8822..61be17dee19 100644 --- a/PC/clinic/winsound.c.h +++ b/PC/clinic/winsound.c.h @@ -20,7 +20,7 @@ static PyObject * winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags); static PyObject * -winsound_PlaySound(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winsound_PlaySound(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"sound", "flags", NULL}; @@ -57,7 +57,7 @@ static PyObject * winsound_Beep_impl(PyObject *module, int frequency, int duration); static PyObject * -winsound_Beep(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winsound_Beep(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"frequency", "duration", NULL}; @@ -90,7 +90,7 @@ static PyObject * winsound_MessageBeep_impl(PyObject *module, int type); static PyObject * -winsound_MessageBeep(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +winsound_MessageBeep(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"type", NULL}; @@ -106,4 +106,4 @@ winsound_MessageBeep(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObje exit: return return_value; } -/*[clinic end generated code: output=d22e41446929d3ef input=a9049054013a1b77]*/ +/*[clinic end generated code: output=beeee8be95667b7d input=a9049054013a1b77]*/ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index a3632115d3b..604493dc5e2 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -126,7 +126,7 @@ update_bases(PyObject *bases, PyObject *const *args, int nargs) /* AC: cannot convert yet, waiting for *args support */ static PyObject * -builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs, +builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *orig_bases; @@ -515,7 +515,7 @@ builtin_callable(PyObject *module, PyObject *obj) } static PyObject * -builtin_breakpoint(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *keywords) +builtin_breakpoint(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords) { PyObject *hook = PySys_GetObject("breakpointhook"); @@ -1112,7 +1112,7 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals, /* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_getattr(PyObject *self, PyObject **args, Py_ssize_t nargs) +builtin_getattr(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *v, *result, *dflt = NULL; PyObject *name; @@ -1417,7 +1417,7 @@ PyTypeObject PyMap_Type = { /* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_next(PyObject *self, PyObject **args, Py_ssize_t nargs) +builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *it, *res; PyObject *def = NULL; @@ -1857,7 +1857,7 @@ builtin_pow_impl(PyObject *module, PyObject *x, PyObject *y, PyObject *z) /* AC: cannot convert yet, waiting for *args support */ static PyObject * -builtin_print(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +builtin_print(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { static const char * const _keywords[] = {"sep", "end", "file", "flush", 0}; static struct _PyArg_Parser _parser = {"|OOOO:print", _keywords, 0}; @@ -2242,7 +2242,7 @@ PyDoc_STRVAR(builtin_sorted__doc__, {"sorted", (PyCFunction)builtin_sorted, METH_FASTCALL | METH_KEYWORDS, builtin_sorted__doc__}, static PyObject * -builtin_sorted(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +builtin_sorted(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *newlist, *v, *seq, *callable; diff --git a/Python/ceval.c b/Python/ceval.c index f6519cff590..287f1df26b5 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3703,10 +3703,10 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount, PyObject * _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, - PyObject **args, Py_ssize_t argcount, - PyObject **kwnames, PyObject **kwargs, + PyObject *const *args, Py_ssize_t argcount, + PyObject *const *kwnames, PyObject *const *kwargs, Py_ssize_t kwcount, int kwstep, - PyObject **defs, Py_ssize_t defcount, + PyObject *const *defs, Py_ssize_t defcount, PyObject *kwdefs, PyObject *closure, PyObject *name, PyObject *qualname) { @@ -3992,8 +3992,10 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, PyObject * PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, - PyObject **args, int argcount, PyObject **kws, int kwcount, - PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) + PyObject *const *args, int argcount, + PyObject *const *kws, int kwcount, + PyObject *const *defs, int defcount, + PyObject *kwdefs, PyObject *closure) { return _PyEval_EvalCodeWithName(_co, globals, locals, args, argcount, diff --git a/Python/clinic/_warnings.c.h b/Python/clinic/_warnings.c.h index 334f9d1988e..68fad230065 100644 --- a/Python/clinic/_warnings.c.h +++ b/Python/clinic/_warnings.c.h @@ -16,7 +16,7 @@ warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category, Py_ssize_t stacklevel, PyObject *source); static PyObject * -warnings_warn(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +warnings_warn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"message", "category", "stacklevel", "source", NULL}; @@ -35,4 +35,4 @@ warnings_warn(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwn exit: return return_value; } -/*[clinic end generated code: output=74b1a7d1ee41816d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=86369ece63001d78 input=a9049054013a1b77]*/ diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h index 3647e62c0d3..285caf94b77 100644 --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -88,7 +88,7 @@ static PyObject * builtin_format_impl(PyObject *module, PyObject *value, PyObject *format_spec); static PyObject * -builtin_format(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_format(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *value; @@ -158,7 +158,7 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename, int optimize); static PyObject * -builtin_compile(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"source", "filename", "mode", "flags", "dont_inherit", "optimize", NULL}; @@ -193,7 +193,7 @@ static PyObject * builtin_divmod_impl(PyObject *module, PyObject *x, PyObject *y); static PyObject * -builtin_divmod(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_divmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *x; @@ -230,7 +230,7 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals, PyObject *locals); static PyObject * -builtin_eval(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_eval(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *source; @@ -268,7 +268,7 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals, PyObject *locals); static PyObject * -builtin_exec(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *source; @@ -322,7 +322,7 @@ static PyObject * builtin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name); static PyObject * -builtin_hasattr(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_hasattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *obj; @@ -367,7 +367,7 @@ builtin_setattr_impl(PyObject *module, PyObject *obj, PyObject *name, PyObject *value); static PyObject * -builtin_setattr(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_setattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *obj; @@ -400,7 +400,7 @@ static PyObject * builtin_delattr_impl(PyObject *module, PyObject *obj, PyObject *name); static PyObject * -builtin_delattr(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_delattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *obj; @@ -509,7 +509,7 @@ static PyObject * builtin_pow_impl(PyObject *module, PyObject *x, PyObject *y, PyObject *z); static PyObject * -builtin_pow(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *x; @@ -546,7 +546,7 @@ static PyObject * builtin_input_impl(PyObject *module, PyObject *prompt); static PyObject * -builtin_input(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_input(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *prompt = NULL; @@ -589,7 +589,7 @@ static PyObject * builtin_round_impl(PyObject *module, PyObject *number, PyObject *ndigits); static PyObject * -builtin_round(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +builtin_round(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"number", "ndigits", NULL}; @@ -624,7 +624,7 @@ static PyObject * builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start); static PyObject * -builtin_sum(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *iterable; @@ -659,7 +659,7 @@ builtin_isinstance_impl(PyObject *module, PyObject *obj, PyObject *class_or_tuple); static PyObject * -builtin_isinstance(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_isinstance(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *obj; @@ -694,7 +694,7 @@ builtin_issubclass_impl(PyObject *module, PyObject *cls, PyObject *class_or_tuple); static PyObject * -builtin_issubclass(PyObject *module, PyObject **args, Py_ssize_t nargs) +builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *cls; @@ -710,4 +710,4 @@ builtin_issubclass(PyObject *module, PyObject **args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=d46a224ac804eef1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9f17c7a87d740374 input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h index 1955e504550..27b83ecc00a 100644 --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -82,7 +82,7 @@ _imp__fix_co_filename_impl(PyObject *module, PyCodeObject *code, PyObject *path); static PyObject * -_imp__fix_co_filename(PyObject *module, PyObject **args, Py_ssize_t nargs) +_imp__fix_co_filename(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyCodeObject *code; @@ -275,7 +275,7 @@ static PyObject * _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file); static PyObject * -_imp_create_dynamic(PyObject *module, PyObject **args, Py_ssize_t nargs) +_imp_create_dynamic(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *spec; @@ -366,7 +366,7 @@ static PyObject * _imp_source_hash_impl(PyObject *module, long key, Py_buffer *source); static PyObject * -_imp_source_hash(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +_imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"key", "source", NULL}; @@ -396,4 +396,4 @@ _imp_source_hash(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject * #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=e8b2c0b0d0a75da8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f0660cd1de6b3a73 input=a9049054013a1b77]*/ diff --git a/Python/clinic/marshal.c.h b/Python/clinic/marshal.c.h index a9466357a55..1ae9332fd3f 100644 --- a/Python/clinic/marshal.c.h +++ b/Python/clinic/marshal.c.h @@ -27,7 +27,7 @@ marshal_dump_impl(PyObject *module, PyObject *value, PyObject *file, int version); static PyObject * -marshal_dump(PyObject *module, PyObject **args, Py_ssize_t nargs) +marshal_dump(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *value; @@ -84,7 +84,7 @@ static PyObject * marshal_dumps_impl(PyObject *module, PyObject *value, int version); static PyObject * -marshal_dumps(PyObject *module, PyObject **args, Py_ssize_t nargs) +marshal_dumps(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *value; @@ -134,4 +134,4 @@ marshal_loads(PyObject *module, PyObject *arg) return return_value; } -/*[clinic end generated code: output=15e284a34abfd26a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=584eb2222d86fdc3 input=a9049054013a1b77]*/ diff --git a/Python/getargs.c b/Python/getargs.c index dd7ca9fed15..56e60f6d207 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -27,9 +27,10 @@ int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *, #ifdef HAVE_DECLSPEC_DLL /* Export functions */ PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...); -PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, +PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject *const *args, Py_ssize_t nargs, const char *format, ...); -PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames, +PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwnames, struct _PyArg_Parser *parser, ...); PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...); PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *, @@ -69,7 +70,7 @@ typedef struct { #define STATIC_FREELIST_ENTRIES 8 /* Forward */ -static int vgetargs1_impl(PyObject *args, PyObject **stack, Py_ssize_t nargs, +static int vgetargs1_impl(PyObject *args, PyObject *const *stack, Py_ssize_t nargs, const char *format, va_list *p_va, int flags); static int vgetargs1(PyObject *, const char *, va_list *, int); static void seterror(Py_ssize_t, const char *, int *, const char *, const char *); @@ -86,7 +87,7 @@ static int vgetargskeywords(PyObject *, PyObject *, const char *, char **, va_list *, int); static int vgetargskeywordsfast(PyObject *, PyObject *, struct _PyArg_Parser *, va_list *, int); -static int vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs, +static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, PyObject *keywords, PyObject *kwnames, struct _PyArg_Parser *parser, va_list *p_va, int flags); @@ -143,7 +144,7 @@ _PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...) int -_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, const char *format, ...) +_PyArg_ParseStack(PyObject *const *args, Py_ssize_t nargs, const char *format, ...) { int retval; va_list va; @@ -155,7 +156,7 @@ _PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, const char *format, ...) } int -_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, const char *format, ...) +_PyArg_ParseStack_SizeT(PyObject *const *args, Py_ssize_t nargs, const char *format, ...) { int retval; va_list va; @@ -250,7 +251,7 @@ cleanreturn(int retval, freelist_t *freelist) static int -vgetargs1_impl(PyObject *compat_args, PyObject **stack, Py_ssize_t nargs, const char *format, +vgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, const char *format, va_list *p_va, int flags) { char msgbuf[256]; @@ -1522,7 +1523,7 @@ _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords, } int -_PyArg_ParseStackAndKeywords(PyObject **args, Py_ssize_t nargs, PyObject *kwnames, +_PyArg_ParseStackAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, struct _PyArg_Parser *parser, ...) { int retval; @@ -1535,7 +1536,7 @@ _PyArg_ParseStackAndKeywords(PyObject **args, Py_ssize_t nargs, PyObject *kwname } int -_PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames, +_PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, struct _PyArg_Parser *parser, ...) { int retval; @@ -1988,7 +1989,7 @@ parser_clear(struct _PyArg_Parser *parser) } static PyObject* -find_keyword(PyObject *kwargs, PyObject *kwnames, PyObject **kwstack, PyObject *key) +find_keyword(PyObject *kwargs, PyObject *kwnames, PyObject *const *kwstack, PyObject *key) { Py_ssize_t i, nkwargs; @@ -2017,7 +2018,7 @@ find_keyword(PyObject *kwargs, PyObject *kwnames, PyObject **kwstack, PyObject * } static int -vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs, +vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, PyObject *kwnames, struct _PyArg_Parser *parser, va_list *p_va, int flags) @@ -2033,7 +2034,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs, PyObject *current_arg; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; freelist_t freelist; - PyObject **kwstack = NULL; + PyObject *const *kwstack = NULL; freelist.entries = static_entries; freelist.first_available = 0; @@ -2395,7 +2396,7 @@ skipitem(const char **p_format, va_list *p_va, int flags) static int -unpack_stack(PyObject **args, Py_ssize_t nargs, const char *name, +unpack_stack(PyObject *const *args, Py_ssize_t nargs, const char *name, Py_ssize_t min, Py_ssize_t max, va_list vargs) { Py_ssize_t i; @@ -2472,7 +2473,7 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m } int -_PyArg_UnpackStack(PyObject **args, Py_ssize_t nargs, const char *name, +_PyArg_UnpackStack(PyObject *const *args, Py_ssize_t nargs, const char *name, Py_ssize_t min, Py_ssize_t max, ...) { int retval; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 24098b9daf8..c0542436fdf 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -97,7 +97,7 @@ PySys_SetObject(const char *name, PyObject *v) } static PyObject * -sys_breakpointhook(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *keywords) +sys_breakpointhook(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords) { assert(!PyErr_Occurred()); const char *envar = Py_GETENV("PYTHONBREAKPOINT"); diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 4cdfebb5107..b704b5a669f 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -710,12 +710,12 @@ def output_templates(self, f): parser_prototype_fastcall = normalize_snippet(""" static PyObject * - {c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs) + {c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs) """) parser_prototype_fastcall_keywords = normalize_snippet(""" static PyObject * - {c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) + {c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) """) # parser_body_fields remembers the fields passed in to the From webhook-mailer at python.org Fri Dec 15 06:26:29 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 15 Dec 2017 11:26:29 -0000 Subject: [Python-checkins] [3.6] bpo-27169: The __debug__ constant is now optimized out at compile time. (GH-4880) (#4882) Message-ID: https://github.com/python/cpython/commit/b82da9ebb20053637e731fd40589e1e52f9f8f6e commit: b82da9ebb20053637e731fd40589e1e52f9f8f6e branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2017-12-15T13:26:26+02:00 summary: [3.6] bpo-27169: The __debug__ constant is now optimized out at compile time. (GH-4880) (#4882) This fixes also bpo-22091.. (cherry picked from commit 3325a6780c81f1ea51190370b5454879c4862a37) files: A Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst M Lib/test/test_builtin.py M Lib/test/test_compile.py M Python/compile.c diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 49c4a53c052..e0dbe784980 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -331,16 +331,16 @@ def test_compile(self): try: assert False except AssertionError: - return (True, f.__doc__) + return (True, f.__doc__, __debug__) else: - return (False, f.__doc__) + return (False, f.__doc__, __debug__) ''' def f(): """doc""" - values = [(-1, __debug__, f.__doc__), - (0, True, 'doc'), - (1, False, 'doc'), - (2, False, None)] - for optval, debugval, docstring in values: + values = [(-1, __debug__, f.__doc__, __debug__), + (0, True, 'doc', True), + (1, False, 'doc', False), + (2, False, None, False)] + for optval, *expected in values: # test both direct compilation and compilation via AST codeobjs = [] codeobjs.append(compile(codestr, "", "exec", optimize=optval)) @@ -350,7 +350,7 @@ def f(): """doc""" ns = {} exec(code, ns) rv = ns['f']() - self.assertEqual(rv, (debugval, docstring)) + self.assertEqual(rv, tuple(expected)) def test_delattr(self): sys.spam = 1 diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index da1db1567b4..7fe34658e04 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -35,6 +35,7 @@ def test_debug_assignment(self): import builtins prev = builtins.__debug__ setattr(builtins, '__debug__', 'sure') + self.assertEqual(__debug__, prev) setattr(builtins, '__debug__', prev) def test_argument_handling(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst new file mode 100644 index 00000000000..81d1d15cbbd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-15-11-50-06.bpo-27169.VO84fQ.rst @@ -0,0 +1,2 @@ +The ``__debug__`` constant is now optimized out at compile time. This fixes also +bpo-22091. diff --git a/Python/compile.c b/Python/compile.c index 4d525a02c81..9984d55858a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1343,13 +1343,15 @@ is_const(expr_ty e) case Ellipsis_kind: case NameConstant_kind: return 1; + case Name_kind: + return _PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__"); default: return 0; } } static PyObject * -get_const_value(expr_ty e) +get_const_value(struct compiler *c, expr_ty e) { switch (e->kind) { case Constant_kind: @@ -1364,6 +1366,9 @@ get_const_value(expr_ty e) return Py_Ellipsis; case NameConstant_kind: return e->v.NameConstant.value; + case Name_kind: + assert(_PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__")); + return c->c_optimize ? Py_False : Py_True; default: assert(!is_const(e)); return NULL; @@ -3035,6 +3040,11 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) !_PyUnicode_EqualToASCIIString(name, "True") && !_PyUnicode_EqualToASCIIString(name, "False")); + if (ctx == Load && _PyUnicode_EqualToASCIIString(name, "__debug__")) { + ADDOP_O(c, LOAD_CONST, c->c_optimize ? Py_False : Py_True, consts); + return 1; + } + op = 0; optype = OP_NAME; scope = PyST_GetScope(c->u->u_ste, mangled); @@ -3298,7 +3308,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end return 0; } for (i = begin; i < end; i++) { - key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + key = get_const_value(c, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); Py_INCREF(key); PyTuple_SET_ITEM(keys, i - begin, key); } @@ -4044,35 +4054,10 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int expr_constant(struct compiler *c, expr_ty e) { - char *id; - switch (e->kind) { - case Ellipsis_kind: - return 1; - case Constant_kind: - return PyObject_IsTrue(e->v.Constant.value); - case Num_kind: - return PyObject_IsTrue(e->v.Num.n); - case Str_kind: - return PyObject_IsTrue(e->v.Str.s); - case Name_kind: - /* optimize away names that can't be reassigned */ - id = PyUnicode_AsUTF8(e->v.Name.id); - if (id && strcmp(id, "__debug__") == 0) - return !c->c_optimize; - return -1; - case NameConstant_kind: { - PyObject *o = e->v.NameConstant.value; - if (o == Py_None) - return 0; - else if (o == Py_True) - return 1; - else if (o == Py_False) - return 0; - } - /* fall through */ - default: - return -1; + if (is_const(e)) { + return PyObject_IsTrue(get_const_value(c, e)); } + return -1; } From webhook-mailer at python.org Fri Dec 15 07:11:45 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 15 Dec 2017 12:11:45 -0000 Subject: [Python-checkins] bpo-30416: Protect the optimizer during constant folding. (#4860) Message-ID: https://github.com/python/cpython/commit/2e3f5701858d1fc04caedefdd9a8ea43810270d2 commit: 2e3f5701858d1fc04caedefdd9a8ea43810270d2 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-15T14:11:43+02:00 summary: bpo-30416: Protect the optimizer during constant folding. (#4860) It no longer spends much time doing complex calculations and no longer consumes much memory for creating large constants that will be dropped later. This fixes also bpo-21074. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst M Lib/test/test_memoryio.py M Lib/test/test_peepholer.py M Python/ast_opt.c diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py index e16c57e9435..cd2faba1791 100644 --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -759,7 +759,8 @@ def test_sizeof(self): check = self.check_sizeof self.assertEqual(object.__sizeof__(io.BytesIO()), basesize) check(io.BytesIO(), basesize ) - check(io.BytesIO(b'a' * 1000), basesize + sys.getsizeof(b'a' * 1000)) + n = 1000 # use a variable to prevent constant folding + check(io.BytesIO(b'a' * n), basesize + sys.getsizeof(b'a' * n)) # Various tests of copy-on-write behaviour for BytesIO. diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index efc0afecf5a..0cc1e92907b 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -175,8 +175,15 @@ def test_folding_of_binops_on_constants(self): self.assertInBytecode(code, 'LOAD_CONST', 'b') # Verify that large sequences do not result from folding - code = compile('a="x"*1000', '', 'single') + code = compile('a="x"*10000', '', 'single') + self.assertInBytecode(code, 'LOAD_CONST', 10000) + self.assertNotIn("x"*10000, code.co_consts) + code = compile('a=1<<1000', '', 'single') self.assertInBytecode(code, 'LOAD_CONST', 1000) + self.assertNotIn(1<<1000, code.co_consts) + code = compile('a=2**1000', '', 'single') + self.assertInBytecode(code, 'LOAD_CONST', 1000) + self.assertNotIn(2**1000, code.co_consts) def test_binary_subscr_on_unicode(self): # valid code get optimized diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst new file mode 100644 index 00000000000..532700e2481 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst @@ -0,0 +1,4 @@ +The optimizer is now protected from spending much time doing complex +calculations and consuming much memory for creating large constants in +constant folding. Increased limits for constants that can be produced in +constant folding. diff --git a/Python/ast_opt.c b/Python/ast_opt.c index e92d6471f91..2f659d08549 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -125,6 +125,132 @@ fold_unaryop(expr_ty node, PyArena *arena) return make_const(node, newval, arena); } +/* Check whether a collection doesn't containing too much items (including + subcollections). This protects from creating a constant that needs + too much time for calculating a hash. + "limit" is the maximal number of items. + Returns the negative number if the total number of items exceeds the + limit. Otherwise returns the limit minus the total number of items. +*/ + +static Py_ssize_t +check_complexity(PyObject *obj, Py_ssize_t limit) +{ + if (PyTuple_Check(obj)) { + Py_ssize_t i; + limit -= PyTuple_GET_SIZE(obj); + for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) { + limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit); + } + return limit; + } + else if (PyFrozenSet_Check(obj)) { + Py_ssize_t i = 0; + PyObject *item; + Py_hash_t hash; + limit -= PySet_GET_SIZE(obj); + while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) { + limit = check_complexity(item, limit); + } + } + return limit; +} + +#define MAX_INT_SIZE 128 /* bits */ +#define MAX_COLLECTION_SIZE 256 /* items */ +#define MAX_STR_SIZE 4096 /* characters */ +#define MAX_TOTAL_ITEMS 1024 /* including nested collections */ + +static PyObject * +safe_multiply(PyObject *v, PyObject *w) +{ + if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) { + size_t vbits = _PyLong_NumBits(v); + size_t wbits = _PyLong_NumBits(w); + if (vbits == (size_t)-1 || wbits == (size_t)-1) { + return NULL; + } + if (vbits + wbits > MAX_INT_SIZE) { + return NULL; + } + } + else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) { + Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) : + PySet_GET_SIZE(w); + if (size) { + long n = PyLong_AsLong(v); + if (n < 0 || n > MAX_COLLECTION_SIZE / size) { + return NULL; + } + if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) { + return NULL; + } + } + } + else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) { + Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) : + PyBytes_GET_SIZE(w); + if (size) { + long n = PyLong_AsLong(v); + if (n < 0 || n > MAX_STR_SIZE / size) { + return NULL; + } + } + } + else if (PyLong_Check(w) && + (PyTuple_Check(v) || PyFrozenSet_Check(v) || + PyUnicode_Check(v) || PyBytes_Check(v))) + { + return safe_multiply(w, v); + } + + return PyNumber_Multiply(v, w); +} + +static PyObject * +safe_power(PyObject *v, PyObject *w) +{ + if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) { + size_t vbits = _PyLong_NumBits(v); + size_t wbits = PyLong_AsSize_t(w); + if (vbits == (size_t)-1 || wbits == (size_t)-1) { + return NULL; + } + if (vbits > MAX_INT_SIZE / wbits) { + return NULL; + } + } + + return PyNumber_Power(v, w, Py_None); +} + +static PyObject * +safe_lshift(PyObject *v, PyObject *w) +{ + if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) { + size_t vbits = _PyLong_NumBits(v); + size_t wbits = PyLong_AsSize_t(w); + if (vbits == (size_t)-1 || wbits == (size_t)-1) { + return NULL; + } + if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) { + return NULL; + } + } + + return PyNumber_Lshift(v, w); +} + +static PyObject * +safe_mod(PyObject *v, PyObject *w) +{ + if (PyUnicode_Check(v) || PyBytes_Check(v)) { + return NULL; + } + + return PyNumber_Remainder(v, w); +} + static int fold_binop(expr_ty node, PyArena *arena) { @@ -147,7 +273,7 @@ fold_binop(expr_ty node, PyArena *arena) newval = PyNumber_Subtract(lv, rv); break; case Mult: - newval = PyNumber_Multiply(lv, rv); + newval = safe_multiply(lv, rv); break; case Div: newval = PyNumber_TrueDivide(lv, rv); @@ -156,13 +282,13 @@ fold_binop(expr_ty node, PyArena *arena) newval = PyNumber_FloorDivide(lv, rv); break; case Mod: - newval = PyNumber_Remainder(lv, rv); + newval = safe_mod(lv, rv); break; case Pow: - newval = PyNumber_Power(lv, rv, Py_None); + newval = safe_power(lv, rv); break; case LShift: - newval = PyNumber_Lshift(lv, rv); + newval = safe_lshift(lv, rv); break; case RShift: newval = PyNumber_Rshift(lv, rv); @@ -180,27 +306,6 @@ fold_binop(expr_ty node, PyArena *arena) return 1; } - if (newval == NULL) { - if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { - return 0; - } - PyErr_Clear(); - return 1; - } - - /* Avoid creating large constants. */ - Py_ssize_t size = PyObject_Size(newval); - if (size == -1) { - if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { - Py_DECREF(newval); - return 0; - } - PyErr_Clear(); - } - else if (size > 20) { - Py_DECREF(newval); - return 1; - } return make_const(node, newval, arena); } From webhook-mailer at python.org Fri Dec 15 07:12:17 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 15 Dec 2017 12:12:17 -0000 Subject: [Python-checkins] [3.6] bpo-30416: Protect the optimizer during constant folding. (#4865) Message-ID: https://github.com/python/cpython/commit/b580f4f2bf49fd3b11f2a046911993560c02492a commit: b580f4f2bf49fd3b11f2a046911993560c02492a branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2017-12-15T14:12:14+02:00 summary: [3.6] bpo-30416: Protect the optimizer during constant folding. (#4865) It no longer spends much time doing complex calculations and no longer consumes much memory for creating large constants that will be dropped later. This fixes also bpo-21074. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst M Lib/test/test_memoryio.py M Lib/test/test_peepholer.py M Python/peephole.c diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py index 55b693e5647..80f3b85b6eb 100644 --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -733,7 +733,8 @@ def test_sizeof(self): check = self.check_sizeof self.assertEqual(object.__sizeof__(io.BytesIO()), basesize) check(io.BytesIO(), basesize ) - check(io.BytesIO(b'a' * 1000), basesize + sys.getsizeof(b'a' * 1000)) + n = 1000 # use a variable to prevent constant folding + check(io.BytesIO(b'a' * n), basesize + sys.getsizeof(b'a' * n)) # Various tests of copy-on-write behaviour for BytesIO. diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index b0336407c3b..e028b096c9f 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -178,8 +178,15 @@ def test_folding_of_binops_on_constants(self): self.assertInBytecode(code, 'LOAD_CONST', 'b') # Verify that large sequences do not result from folding - code = compile('a="x"*1000', '', 'single') + code = compile('a="x"*10000', '', 'single') + self.assertInBytecode(code, 'LOAD_CONST', 10000) + self.assertNotIn("x"*10000, code.co_consts) + code = compile('a=1<<1000', '', 'single') self.assertInBytecode(code, 'LOAD_CONST', 1000) + self.assertNotIn(1<<1000, code.co_consts) + code = compile('a=2**1000', '', 'single') + self.assertInBytecode(code, 'LOAD_CONST', 1000) + self.assertNotIn(2**1000, code.co_consts) def test_binary_subscr_on_unicode(self): # valid code get optimized diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst new file mode 100644 index 00000000000..8db577bfdb3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-14-11-48-19.bpo-30416.hlHo_9.rst @@ -0,0 +1,3 @@ +The optimizer is now protected from spending much time doing complex +calculations and consuming much memory for creating large constants in +constant folding. diff --git a/Python/peephole.c b/Python/peephole.c index dd8f3e4807f..31d4e92cfd3 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -167,6 +167,37 @@ copy_op_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned char op, return maxi - 1; } +/* Check whether a collection doesn't containing too much items (including + subcollections). This protects from creating a constant that needs + too much time for calculating a hash. + "limit" is the maximal number of items. + Returns the negative number if the total number of items exceeds the + limit. Otherwise returns the limit minus the total number of items. +*/ + +static Py_ssize_t +check_complexity(PyObject *obj, Py_ssize_t limit) +{ + if (PyTuple_Check(obj)) { + Py_ssize_t i; + limit -= PyTuple_GET_SIZE(obj); + for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) { + limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit); + } + return limit; + } + else if (PyFrozenSet_Check(obj)) { + Py_ssize_t i = 0; + PyObject *item; + Py_hash_t hash; + limit -= PySet_GET_SIZE(obj); + while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) { + limit = check_complexity(item, limit); + } + } + return limit; +} + /* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n with LOAD_CONST (c1, c2, ... cn). The consts table must still be in list form so that the @@ -218,6 +249,101 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end); } +#define MAX_INT_SIZE 128 /* bits */ +#define MAX_COLLECTION_SIZE 20 /* items */ +#define MAX_STR_SIZE 20 /* characters */ +#define MAX_TOTAL_ITEMS 1024 /* including nested collections */ + +static PyObject * +safe_multiply(PyObject *v, PyObject *w) +{ + if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) { + size_t vbits = _PyLong_NumBits(v); + size_t wbits = _PyLong_NumBits(w); + if (vbits == (size_t)-1 || wbits == (size_t)-1) { + return NULL; + } + if (vbits + wbits > MAX_INT_SIZE) { + return NULL; + } + } + else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) { + Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) : + PySet_GET_SIZE(w); + if (size) { + long n = PyLong_AsLong(v); + if (n < 0 || n > MAX_COLLECTION_SIZE / size) { + return NULL; + } + if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) { + return NULL; + } + } + } + else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) { + Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) : + PyBytes_GET_SIZE(w); + if (size) { + long n = PyLong_AsLong(v); + if (n < 0 || n > MAX_STR_SIZE / size) { + return NULL; + } + } + } + else if (PyLong_Check(w) && + (PyTuple_Check(v) || PyFrozenSet_Check(v) || + PyUnicode_Check(v) || PyBytes_Check(v))) + { + return safe_multiply(w, v); + } + + return PyNumber_Multiply(v, w); +} + +static PyObject * +safe_power(PyObject *v, PyObject *w) +{ + if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) { + size_t vbits = _PyLong_NumBits(v); + size_t wbits = PyLong_AsSize_t(w); + if (vbits == (size_t)-1 || wbits == (size_t)-1) { + return NULL; + } + if (vbits > MAX_INT_SIZE / wbits) { + return NULL; + } + } + + return PyNumber_Power(v, w, Py_None); +} + +static PyObject * +safe_lshift(PyObject *v, PyObject *w) +{ + if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) { + size_t vbits = _PyLong_NumBits(v); + size_t wbits = PyLong_AsSize_t(w); + if (vbits == (size_t)-1 || wbits == (size_t)-1) { + return NULL; + } + if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) { + return NULL; + } + } + + return PyNumber_Lshift(v, w); +} + +static PyObject * +safe_mod(PyObject *v, PyObject *w) +{ + if (PyUnicode_Check(v) || PyBytes_Check(v)) { + return NULL; + } + + return PyNumber_Remainder(v, w); +} + /* Replace LOAD_CONST c1, LOAD_CONST c2, BINOP with LOAD_CONST binop(c1,c2) The consts table must still be in list form so that the @@ -234,7 +360,7 @@ fold_binops_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, PyObject *consts, PyObject **objs) { PyObject *newconst, *v, *w; - Py_ssize_t len_consts, size; + Py_ssize_t len_consts; /* Pre-conditions */ assert(PyList_CheckExact(consts)); @@ -245,10 +371,10 @@ fold_binops_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, w = objs[1]; switch (opcode) { case BINARY_POWER: - newconst = PyNumber_Power(v, w, Py_None); + newconst = safe_power(v, w); break; case BINARY_MULTIPLY: - newconst = PyNumber_Multiply(v, w); + newconst = safe_multiply(v, w); break; case BINARY_TRUE_DIVIDE: newconst = PyNumber_TrueDivide(v, w); @@ -257,7 +383,7 @@ fold_binops_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, newconst = PyNumber_FloorDivide(v, w); break; case BINARY_MODULO: - newconst = PyNumber_Remainder(v, w); + newconst = safe_mod(v, w); break; case BINARY_ADD: newconst = PyNumber_Add(v, w); @@ -269,7 +395,7 @@ fold_binops_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, newconst = PyObject_GetItem(v, w); break; case BINARY_LSHIFT: - newconst = PyNumber_Lshift(v, w); + newconst = safe_lshift(v, w); break; case BINARY_RSHIFT: newconst = PyNumber_Rshift(v, w); @@ -296,16 +422,6 @@ fold_binops_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, } return -1; } - size = PyObject_Size(newconst); - if (size == -1) { - if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { - return -1; - } - PyErr_Clear(); - } else if (size > 20) { - Py_DECREF(newconst); - return -1; - } /* Append folded constant into consts table */ if (PyList_Append(consts, newconst)) { From webhook-mailer at python.org Fri Dec 15 07:13:44 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 15 Dec 2017 12:13:44 -0000 Subject: [Python-checkins] bpo-32265: Classify class and static methods of builtin types. (#4776) Message-ID: https://github.com/python/cpython/commit/3327a2ddf1eaf8cc678f0219ba9edf7d632d1b20 commit: 3327a2ddf1eaf8cc678f0219ba9edf7d632d1b20 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-15T14:13:41+02:00 summary: bpo-32265: Classify class and static methods of builtin types. (#4776) Add types.ClassMethodDescriptorType for unbound class methods. files: A Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst M Doc/library/types.rst M Lib/inspect.py M Lib/test/test_inspect.py M Lib/test/test_types.py M Lib/types.py diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 89aca9c9df8..bbc1d1301d2 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -155,6 +155,14 @@ Standard names are defined for the following types: .. versionadded:: 3.7 +.. data:: ClassMethodDescriptorType + + The type of *unbound* class methods of some built-in data types such as + ``dict.__dict__['fromkeys']``. + + .. versionadded:: 3.7 + + .. class:: ModuleType(name, doc=None) The type of :term:`modules `. Constructor takes the name of the diff --git a/Lib/inspect.py b/Lib/inspect.py index 8c121ce96c4..b7551878b74 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -457,10 +457,10 @@ def classify_class_attrs(cls): continue obj = get_obj if get_obj is not None else dict_obj # Classify the object or its descriptor. - if isinstance(dict_obj, staticmethod): + if isinstance(dict_obj, (staticmethod, types.BuiltinMethodType)): kind = "static method" obj = dict_obj - elif isinstance(dict_obj, classmethod): + elif isinstance(dict_obj, (classmethod, types.ClassMethodDescriptorType)): kind = "class method" obj = dict_obj elif isinstance(dict_obj, property): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 5b5bc650d2f..e8eddbedf7e 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -858,7 +858,8 @@ def m1(self): pass attrs = attrs_wo_objs(A) - self.assertIn(('__new__', 'method', object), attrs, 'missing __new__') + self.assertIn(('__new__', 'static method', object), attrs, + 'missing __new__') self.assertIn(('__init__', 'method', object), attrs, 'missing __init__') self.assertIn(('s', 'static method', A), attrs, 'missing static method') @@ -923,6 +924,18 @@ def test_classify_builtin_types(self): if isinstance(builtin, type): inspect.classify_class_attrs(builtin) + attrs = attrs_wo_objs(bool) + self.assertIn(('__new__', 'static method', bool), attrs, + 'missing __new__') + self.assertIn(('from_bytes', 'class method', int), attrs, + 'missing class method') + self.assertIn(('to_bytes', 'method', int), attrs, + 'missing plain method') + self.assertIn(('__add__', 'method', int), attrs, + 'missing plain method') + self.assertIn(('__and__', 'method', bool), attrs, + 'missing plain method') + def test_classify_DynamicClassAttribute(self): class Meta(type): def __getattr__(self, name): diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 47488a615b1..56848c1bf87 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -594,6 +594,10 @@ def test_method_descriptor_types(self): self.assertIsInstance(''.join, types.BuiltinMethodType) self.assertIsInstance([].append, types.BuiltinMethodType) + self.assertIsInstance(int.__dict__['from_bytes'], types.ClassMethodDescriptorType) + self.assertIsInstance(int.from_bytes, types.BuiltinMethodType) + self.assertIsInstance(int.__new__, types.BuiltinMethodType) + class MappingProxyTests(unittest.TestCase): mappingproxy = types.MappingProxyType diff --git a/Lib/types.py b/Lib/types.py index c5976f3057f..ce4652f3718 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -39,6 +39,7 @@ def _m(self): pass WrapperDescriptorType = type(object.__init__) MethodWrapperType = type(object().__str__) MethodDescriptorType = type(str.join) +ClassMethodDescriptorType = type(dict.__dict__['fromkeys']) ModuleType = type(sys) diff --git a/Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst b/Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst new file mode 100644 index 00000000000..16686c1b418 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst @@ -0,0 +1,3 @@ +All class and static methods of builtin types now are correctly classified +by inspect.classify_class_attrs() and grouped in pydoc ouput. Added +types.ClassMethodDescriptorType for unbound class methods of builtin types. From webhook-mailer at python.org Fri Dec 15 09:23:26 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 14:23:26 -0000 Subject: [Python-checkins] bpo-28393: Update encoding lookup docs wrt bpo-27938 (GH-4871) (#4881) Message-ID: https://github.com/python/cpython/commit/77bf6da7258b4a312e224860ea50ac010aa17c1e commit: 77bf6da7258b4a312e224860ea50ac010aa17c1e branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Victor Stinner date: 2017-12-15T15:23:24+01:00 summary: bpo-28393: Update encoding lookup docs wrt bpo-27938 (GH-4871) (#4881) (cherry picked from commit 297fd876aad8ef443d8992618de22c46dbda258b) files: M Doc/library/codecs.rst diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 6e249ecf2b1..74b24e10ede 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -977,10 +977,14 @@ e.g. ``'utf-8'`` is a valid alias for the ``'utf_8'`` codec. Some common encodings can bypass the codecs lookup machinery to improve performance. These optimization opportunities are only - recognized by CPython for a limited set of aliases: utf-8, utf8, - latin-1, latin1, iso-8859-1, mbcs (Windows only), ascii, utf-16, - and utf-32. Using alternative spellings for these encodings may - result in slower execution. + recognized by CPython for a limited set of (case insensitive) + aliases: utf-8, utf8, latin-1, latin1, iso-8859-1, iso8859-1, mbcs + (Windows only), ascii, us-ascii, utf-16, utf16, utf-32, utf32, and + the same using underscores instead of dashes. Using alternative + aliases for these encodings may result in slower execution. + + .. versionchanged:: 3.6 + Optimization opportunity recognized for us-ascii. Many of the character sets support the same languages. They vary in individual characters (e.g. whether the EURO SIGN is supported or not), and in the From webhook-mailer at python.org Fri Dec 15 10:29:09 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 15:29:09 -0000 Subject: [Python-checkins] bpo-32329: Add versionchanged to -R option doc (#4884) Message-ID: https://github.com/python/cpython/commit/642d67b4f25262889b43f91ad2a96ca0e37fd5a2 commit: 642d67b4f25262889b43f91ad2a96ca0e37fd5a2 branch: master author: Victor Stinner committer: GitHub date: 2017-12-15T16:29:01+01:00 summary: bpo-32329: Add versionchanged to -R option doc (#4884) files: M Doc/using/cmdline.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 598eb2583d3..3915f336a5a 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -295,6 +295,9 @@ Miscellaneous options :envvar:`PYTHONHASHSEED` allows you to set a fixed value for the hash seed secret. + .. versionchanged:: 3.7 + The option is no longer ignored. + .. versionadded:: 3.2.3 From webhook-mailer at python.org Fri Dec 15 10:29:26 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 15:29:26 -0000 Subject: [Python-checkins] bpo-32294: Fix multiprocessing test_semaphore_tracker() (#4885) Message-ID: https://github.com/python/cpython/commit/9402c8367bf6ada1b84f620ad957750c33adbaf9 commit: 9402c8367bf6ada1b84f620ad957750c33adbaf9 branch: master author: Victor Stinner committer: GitHub date: 2017-12-15T16:29:24+01:00 summary: bpo-32294: Fix multiprocessing test_semaphore_tracker() (#4885) Run the child process with -E option to ignore the PYTHONWARNINGS environment variable. files: M Lib/test/_test_multiprocessing.py diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 60385536992..7575c5d3681 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4365,7 +4365,7 @@ def test_semaphore_tracker(self): ''' r, w = os.pipe() p = subprocess.Popen([sys.executable, - '-c', cmd % (w, w)], + '-E', '-c', cmd % (w, w)], pass_fds=[w], stderr=subprocess.PIPE) os.close(w) From webhook-mailer at python.org Fri Dec 15 10:29:51 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 15:29:51 -0000 Subject: [Python-checkins] compile.c: Remove unused varible (#4886) Message-ID: https://github.com/python/cpython/commit/da2b79867eb54c9964597ba30123bf9196baf0c2 commit: da2b79867eb54c9964597ba30123bf9196baf0c2 branch: 3.6 author: Victor Stinner committer: GitHub date: 2017-12-15T16:29:48+01:00 summary: compile.c: Remove unused varible (#4886) Fix a compiler warning. files: M Python/compile.c diff --git a/Python/compile.c b/Python/compile.c index 9984d55858a..13b4fb83076 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -5155,7 +5155,6 @@ compute_code_flags(struct compiler *c) { PySTEntryObject *ste = c->u->u_ste; int flags = 0; - Py_ssize_t n; if (ste->ste_type == FunctionBlock) { flags |= CO_NEWLOCALS | CO_OPTIMIZED; if (ste->ste_nested) From webhook-mailer at python.org Fri Dec 15 11:26:50 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 16:26:50 -0000 Subject: [Python-checkins] bpo-32294: Fix multiprocessing test_semaphore_tracker() (GH-4885) (#4887) Message-ID: https://github.com/python/cpython/commit/7d1fbecd6a27a3693e05541ffc62b7885edfd8b3 commit: 7d1fbecd6a27a3693e05541ffc62b7885edfd8b3 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Victor Stinner date: 2017-12-15T17:26:46+01:00 summary: bpo-32294: Fix multiprocessing test_semaphore_tracker() (GH-4885) (#4887) Run the child process with -E option to ignore the PYTHONWARNINGS environment variable. (cherry picked from commit 9402c8367bf6ada1b84f620ad957750c33adbaf9) files: M Lib/test/_test_multiprocessing.py diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 774e797f02e..e4d60f88042 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4146,7 +4146,7 @@ def test_semaphore_tracker(self): ''' r, w = os.pipe() p = subprocess.Popen([sys.executable, - '-c', cmd % (w, w)], + '-E', '-c', cmd % (w, w)], pass_fds=[w], stderr=subprocess.PIPE) os.close(w) From webhook-mailer at python.org Fri Dec 15 13:07:04 2017 From: webhook-mailer at python.org (Mariatta) Date: Fri, 15 Dec 2017 18:07:04 -0000 Subject: [Python-checkins] F-strings docs: link to Format Specifiers (GH-4888) Message-ID: https://github.com/python/cpython/commit/d924fa523df766dbf2f8b6a28ae502eb3433bfe5 commit: d924fa523df766dbf2f8b6a28ae502eb3433bfe5 branch: master author: Mariatta committer: GitHub date: 2017-12-15T10:07:01-08:00 summary: F-strings docs: link to Format Specifiers (GH-4888) Link to the Format Specification Mini Language section from f-strings' documentation. files: M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index ee3fbc13e2b..86e55e4d9c8 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -656,7 +656,8 @@ the final value of the whole string. Top-level format specifiers may include nested replacement fields. These nested fields may include their own conversion fields and -format specifiers, but may not include more deeply-nested replacement fields. +:ref:`format specifiers `, but may not include more +deeply-nested replacement fields. Formatted string literals may be concatenated, but replacement fields cannot be split across literals. From webhook-mailer at python.org Fri Dec 15 13:11:20 2017 From: webhook-mailer at python.org (Mariatta) Date: Fri, 15 Dec 2017 18:11:20 -0000 Subject: [Python-checkins] F-strings docs: link to Format Specifiers (GH-4888) (GH-4889) Message-ID: https://github.com/python/cpython/commit/5a9f379435c1dbe812da885b2aa869c3dbf65f35 commit: 5a9f379435c1dbe812da885b2aa869c3dbf65f35 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2017-12-15T10:11:17-08:00 summary: F-strings docs: link to Format Specifiers (GH-4888) (GH-4889) Link to the Format Specification Mini Language section from f-strings' documentation. (cherry picked from commit d924fa523df766dbf2f8b6a28ae502eb3433bfe5) files: M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 4a5abf62768..30dc72184ae 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -656,7 +656,8 @@ the final value of the whole string. Top-level format specifiers may include nested replacement fields. These nested fields may include their own conversion fields and -format specifiers, but may not include more deeply-nested replacement fields. +:ref:`format specifiers `, but may not include more +deeply-nested replacement fields. Formatted string literals may be concatenated, but replacement fields cannot be split across literals. From webhook-mailer at python.org Fri Dec 15 16:17:57 2017 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 15 Dec 2017 21:17:57 -0000 Subject: [Python-checkins] Minor wording tweak for itertools documentation (#4893) Message-ID: https://github.com/python/cpython/commit/6693d7af6670f8bda331e0b63bb77fce2e3efe9c commit: 6693d7af6670f8bda331e0b63bb77fce2e3efe9c branch: master author: Raymond Hettinger committer: GitHub date: 2017-12-15T13:17:55-08:00 summary: Minor wording tweak for itertools documentation (#4893) files: M Doc/library/itertools.rst diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index a91894059d0..5af5422eefe 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -32,7 +32,7 @@ operator can be mapped across two vectors to form an efficient dot-product: ``sum(map(operator.mul, vector1, vector2))``. -**Infinite Iterators:** +**Infinite iterators:** ================== ================= ================================================= ========================================= Iterator Arguments Results Example @@ -61,7 +61,7 @@ Iterator Arguments Results :func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-`` ============================ ============================ ================================================= ============================================================= -**Combinatoric generators:** +**Combinatoric iterators:** ============================================== ==================== ============================================================= Iterator Arguments Results From webhook-mailer at python.org Fri Dec 15 16:28:53 2017 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 15 Dec 2017 21:28:53 -0000 Subject: [Python-checkins] Minor wording tweak for itertools documentation (GH-4893) (#4894) Message-ID: https://github.com/python/cpython/commit/dab4cf210cfbc1ecc9def63c1929ec801c1a0068 commit: dab4cf210cfbc1ecc9def63c1929ec801c1a0068 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2017-12-15T13:28:50-08:00 summary: Minor wording tweak for itertools documentation (GH-4893) (#4894) (cherry picked from commit 6693d7af6670f8bda331e0b63bb77fce2e3efe9c) files: M Doc/library/itertools.rst diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 594af39f60f..d01ce8f3757 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -32,7 +32,7 @@ operator can be mapped across two vectors to form an efficient dot-product: ``sum(map(operator.mul, vector1, vector2))``. -**Infinite Iterators:** +**Infinite iterators:** ================== ================= ================================================= ========================================= Iterator Arguments Results Example @@ -61,7 +61,7 @@ Iterator Arguments Results :func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-`` ============================ ============================ ================================================= ============================================================= -**Combinatoric generators:** +**Combinatoric iterators:** ============================================== ==================== ============================================================= Iterator Arguments Results From webhook-mailer at python.org Fri Dec 15 17:06:25 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 15 Dec 2017 22:06:25 -0000 Subject: [Python-checkins] bpo-29240: Don't define decode_locale() on macOS (#4895) Message-ID: https://github.com/python/cpython/commit/d2b02310acbfe6c978a8ad3cd3ac8b3f12927442 commit: d2b02310acbfe6c978a8ad3cd3ac8b3f12927442 branch: master author: Victor Stinner committer: GitHub date: 2017-12-15T23:06:17+01:00 summary: bpo-29240: Don't define decode_locale() on macOS (#4895) Don't define decode_locale() nor encode_locale() on macOS or Android. files: M Python/fileutils.c diff --git a/Python/fileutils.c b/Python/fileutils.c index 03cc37958a0..4b69049ce58 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -249,6 +249,7 @@ decode_ascii_surrogateescape(const char *arg, size_t *size) } #endif +#if !defined(__APPLE__) && !defined(__ANDROID__) static wchar_t* decode_locale(const char* arg, size_t *size) { @@ -364,6 +365,7 @@ decode_locale(const char* arg, size_t *size) } return NULL; } +#endif /* Decode a byte string from the locale encoding with the @@ -453,6 +455,7 @@ _Py_EncodeLocaleUTF8(const wchar_t *text, size_t *error_pos) return cpath; } +#if !defined(__APPLE__) && !defined(__ANDROID__) static char* encode_locale(const wchar_t *text, size_t *error_pos) { @@ -516,6 +519,7 @@ encode_locale(const wchar_t *text, size_t *error_pos) } return result; } +#endif /* Encode a wide character string to the locale encoding with the surrogateescape error handler: surrogate characters in the range From webhook-mailer at python.org Fri Dec 15 19:29:42 2017 From: webhook-mailer at python.org (Brett Cannon) Date: Sat, 16 Dec 2017 00:29:42 -0000 Subject: [Python-checkins] bpo-32248: Implement importlib.abc.ResourceReader (GH-4892) Message-ID: https://github.com/python/cpython/commit/4ac5150e068a3a795ef00465f6dff51747b62b91 commit: 4ac5150e068a3a795ef00465f6dff51747b62b91 branch: master author: Brett Cannon committer: GitHub date: 2017-12-15T16:29:35-08:00 summary: bpo-32248: Implement importlib.abc.ResourceReader (GH-4892) files: A Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst M Doc/library/importlib.rst M Lib/importlib/abc.py M Lib/test/test_importlib/test_abc.py diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 3cafb41d447..eeccc9d40e6 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -233,6 +233,7 @@ ABC hierarchy:: | +-- MetaPathFinder | +-- PathEntryFinder +-- Loader + +-- ResourceReader +-- ResourceLoader --------+ +-- InspectLoader | +-- ExecutionLoader --+ @@ -468,6 +469,71 @@ ABC hierarchy:: The import machinery now takes care of this automatically. +.. class:: ResourceReader + + An :term:`abstract base class` for :term:`package` + :term:`loaders ` to provide the ability to read + *resources*. + + From the perspective of this ABC, a *resource* is a binary + artifact that is shipped within a package. Typically this is + something like a data file that lives next to the ``__init__.py`` + file of the package. The purpose of this class is to help abstract + out the accessing of such data files so that it does not matter if + the package and its data file(s) are stored in a e.g. zip file + versus on the file system. + + For any of methods of this class, a *resource* argument is + expected to be a :term:`file-like object` which represents + conceptually just a file name. This means that no subdirectory + paths should be included in the *resource* argument. This is + because the location of the package that the loader is for acts + as the "directory". Hence the metaphor for directories and file + names is packages and resources, respectively. This is also why + instances of this class are expected to directly correlate to + a specific package (instead of potentially representing multiple + packages or a module). + + .. versionadded:: 3.7 + + .. abstractmethod:: open_resource(resource) + + Returns an opened, :term:`file-like object` for binary reading + of the *resource*. + + If the resource cannot be found, :exc:`FileNotFoundError` is + raised. + + .. abstractmethod:: resource_path(resource) + + Returns the file system path to the *resource*. + + If the resource does not concretely exist on the file system, + raise :exc:`FileNotFoundError`. + + .. abstractmethod:: is_resource(name) + + Returns ``True`` if the named *name* is considered a resource. + :exc:`FileNotFoundError` is raised if *name* does not exist. + + .. abstractmethod:: contents() + + Returns an :term:`iterator` of strings over the contents of + the package. Do note that it is not required that all names + returned by the iterator be actual resources, e.g. it is + acceptable to return names for which :meth:`is_resource` would + be false. + + Allowing non-resource names to be returned is to allow for + situations where how a package and its resources are stored + are known a priori and the non-resource names would be useful. + For instance, returning subdirectory names is allowed so that + when it is known that the package and resources are stored on + the file system then those subdirectory names can be used. + + The abstract method returns an empty iterator. + + .. class:: ResourceLoader An abstract base class for a :term:`loader` which implements the optional diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py index d7cadf2ee74..b772db3758c 100644 --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -340,3 +340,41 @@ def set_data(self, path, data): """ _register(SourceLoader, machinery.SourceFileLoader) + + +class ResourceReader(Loader): + + """Abstract base class for loaders to provide resource reading support.""" + + @abc.abstractmethod + def open_resource(self, resource): + """Return an opened, file-like object for binary reading. + + The 'resource' argument is expected to represent only a file name + and thus not contain any subdirectory components. + + If the resource cannot be found, FileNotFoundError is raised. + """ + raise FileNotFoundError + + @abc.abstractmethod + def resource_path(self, resource): + """Return the file system path to the specified resource. + + The 'resource' argument is expected to represent only a file name + and thus not contain any subdirectory components. + + If the resource does not exist on the file system, raise + FileNotFoundError. + """ + raise FileNotFoundError + + @abc.abstractmethod + def is_resource(self, name): + """Return True if the named 'name' is consider a resource.""" + raise FileNotFoundError + + @abc.abstractmethod + def contents(self): + """Return an iterator of strings over the contents of the package.""" + return iter([]) diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py index 4ba28c6638b..f1e1db35623 100644 --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -305,6 +305,45 @@ def test_get_filename(self): ) = test_util.test_both(InspectLoaderDefaultsTests) +class ResourceReader: + + def open_resource(self, *args, **kwargs): + return super().open_resource(*args, **kwargs) + + def resource_path(self, *args, **kwargs): + return super().resource_path(*args, **kwargs) + + def is_resource(self, *args, **kwargs): + return super().is_resource(*args, **kwargs) + + def contents(self, *args, **kwargs): + return super().contents(*args, **kwargs) + + +class ResourceReaderDefaultsTests(ABCTestHarness): + + SPLIT = make_abc_subclasses(ResourceReader) + + def test_open_resource(self): + with self.assertRaises(FileNotFoundError): + self.ins.open_resource('dummy_file') + + def test_resource_path(self): + with self.assertRaises(FileNotFoundError): + self.ins.resource_path('dummy_file') + + def test_is_resource(self): + with self.assertRaises(FileNotFoundError): + self.ins.is_resource('dummy_file') + + def test_contents(self): + self.assertEqual([], list(self.ins.contents())) + +(Frozen_RRDefaultTests, + Source_RRDefaultsTests + ) = test_util.test_both(ResourceReaderDefaultsTests) + + ##### MetaPathFinder concrete methods ########################################## class MetaPathFinderFindModuleTests: diff --git a/Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst b/Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst new file mode 100644 index 00000000000..f77cdb03dde --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst @@ -0,0 +1,2 @@ +Add :class:`importlib.abc.ResourceReader` as an ABC for loaders to provide a +unified API for reading resources contained within packages. From webhook-mailer at python.org Fri Dec 15 19:32:27 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 16 Dec 2017 00:32:27 -0000 Subject: [Python-checkins] bpo-27456: Ensure TCP_NODELAY is set on linux (#4231) Message-ID: https://github.com/python/cpython/commit/e796b2fe26f220107ac50667de6cc86c82b465e3 commit: e796b2fe26f220107ac50667de6cc86c82b465e3 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-15T19:32:25-05:00 summary: bpo-27456: Ensure TCP_NODELAY is set on linux (#4231) files: A Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst M Lib/asyncio/base_events.py M Lib/asyncio/selector_events.py M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 80d2b693f1d..398497de09f 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -82,18 +82,24 @@ def _set_reuseport(sock): 'SO_REUSEPORT defined but not implemented.') -def _is_stream_socket(sock): - # Linux's socket.type is a bitmask that can include extra info - # about socket, therefore we can't do simple - # `sock_type == socket.SOCK_STREAM`. - return (sock.type & socket.SOCK_STREAM) == socket.SOCK_STREAM +def _is_stream_socket(sock_type): + if hasattr(socket, 'SOCK_NONBLOCK'): + # Linux's socket.type is a bitmask that can include extra info + # about socket (like SOCK_NONBLOCK bit), therefore we can't do simple + # `sock_type == socket.SOCK_STREAM`, see + # https://github.com/torvalds/linux/blob/v4.13/include/linux/net.h#L77 + # for more details. + return (sock_type & 0xF) == socket.SOCK_STREAM + else: + return sock_type == socket.SOCK_STREAM -def _is_dgram_socket(sock): - # Linux's socket.type is a bitmask that can include extra info - # about socket, therefore we can't do simple - # `sock_type == socket.SOCK_DGRAM`. - return (sock.type & socket.SOCK_DGRAM) == socket.SOCK_DGRAM +def _is_dgram_socket(sock_type): + if hasattr(socket, 'SOCK_NONBLOCK'): + # See the comment in `_is_stream_socket`. + return (sock_type & 0xF) == socket.SOCK_DGRAM + else: + return sock_type == socket.SOCK_DGRAM def _ipaddr_info(host, port, family, type, proto): @@ -106,14 +112,9 @@ def _ipaddr_info(host, port, family, type, proto): host is None: return None - if type == socket.SOCK_STREAM: - # Linux only: - # getaddrinfo() can raise when socket.type is a bit mask. - # So if socket.type is a bit mask of SOCK_STREAM, and say - # SOCK_NONBLOCK, we simply return None, which will trigger - # a call to getaddrinfo() letting it process this request. + if _is_stream_socket(type): proto = socket.IPPROTO_TCP - elif type == socket.SOCK_DGRAM: + elif _is_dgram_socket(type): proto = socket.IPPROTO_UDP else: return None @@ -758,7 +759,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): if sock is None: raise ValueError( 'host and port was not specified and no sock specified') - if not _is_stream_socket(sock): + if not _is_stream_socket(sock.type): # We allow AF_INET, AF_INET6, AF_UNIX as long as they # are SOCK_STREAM. # We support passing AF_UNIX sockets even though we have @@ -808,7 +809,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): allow_broadcast=None, sock=None): """Create datagram connection.""" if sock is not None: - if not _is_dgram_socket(sock): + if not _is_dgram_socket(sock.type): raise ValueError( f'A UDP Socket was expected, got {sock!r}') if (local_addr or remote_addr or @@ -1036,7 +1037,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): else: if sock is None: raise ValueError('Neither host/port nor sock were specified') - if not _is_stream_socket(sock): + if not _is_stream_socket(sock.type): raise ValueError(f'A Stream Socket was expected, got {sock!r}') sockets = [sock] @@ -1059,7 +1060,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): This method is a coroutine. When completed, the coroutine returns a (transport, protocol) pair. """ - if not _is_stream_socket(sock): + if not _is_stream_socket(sock.type): raise ValueError(f'A Stream Socket was expected, got {sock!r}') transport, protocol = await self._create_connection_transport( diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 78ebf3e5fca..cb33cd34b87 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -41,7 +41,7 @@ def _test_selector_event(selector, fd, event): if hasattr(socket, 'TCP_NODELAY'): def _set_nodelay(sock): if (sock.family in {socket.AF_INET, socket.AF_INET6} and - sock.type == socket.SOCK_STREAM and + base_events._is_stream_socket(sock.type) and sock.proto == socket.IPPROTO_TCP): sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) else: diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index b9bdf8786f2..50d78c88545 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -222,7 +222,7 @@ def _child_watcher_callback(self, pid, returncode, transp): if sock is None: raise ValueError('no path and sock were specified') if (sock.family != socket.AF_UNIX or - not base_events._is_stream_socket(sock)): + not base_events._is_stream_socket(sock.type)): raise ValueError( f'A UNIX Domain Stream Socket was expected, got {sock!r}') sock.setblocking(False) @@ -276,7 +276,7 @@ def _child_watcher_callback(self, pid, returncode, transp): 'path was not specified, and no sock specified') if (sock.family != socket.AF_UNIX or - not base_events._is_stream_socket(sock)): + not base_events._is_stream_socket(sock.type)): raise ValueError( f'A UNIX Domain Stream Socket was expected, got {sock!r}') diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index f8427cd5a86..1d45cf86425 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -107,13 +107,6 @@ def test_ipaddr_info(self): self.assertIsNone( base_events._ipaddr_info('::3%lo0', 1, INET6, STREAM, TCP)) - if hasattr(socket, 'SOCK_NONBLOCK'): - self.assertEqual( - None, - base_events._ipaddr_info( - '1.2.3.4', 1, INET, STREAM | socket.SOCK_NONBLOCK, TCP)) - - def test_port_parameter_types(self): # Test obscure kinds of arguments for "port". INET = socket.AF_INET diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 04b0f97b2ab..b1ca3fcf0b1 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -15,6 +15,7 @@ from asyncio.selector_events import _SelectorTransport from asyncio.selector_events import _SelectorSocketTransport from asyncio.selector_events import _SelectorDatagramTransport +from asyncio.selector_events import _set_nodelay from test.test_asyncio import utils as test_utils @@ -1493,5 +1494,31 @@ def test_fatal_error_connected(self, m_exc): 'Fatal error on transport\nprotocol:.*\ntransport:.*'), exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY)) + +class TestSelectorUtils(test_utils.TestCase): + def check_set_nodelay(self, sock): + opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) + self.assertFalse(opt) + + _set_nodelay(sock) + + opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) + self.assertTrue(opt) + + @unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'), + 'need socket.TCP_NODELAY') + def test_set_nodelay(self): + sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, + proto=socket.IPPROTO_TCP) + with sock: + self.check_set_nodelay(sock) + + sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, + proto=socket.IPPROTO_TCP) + with sock: + sock.setblocking(False) + self.check_set_nodelay(sock) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst b/Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst new file mode 100644 index 00000000000..fa7b5616bb3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst @@ -0,0 +1 @@ +Ensure TCP_NODELAY is set on Linux. Tests by Victor Stinner. From lp_benchmark_robot at intel.com Fri Dec 15 20:38:01 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 15 Dec 2017 17:38:01 -0800 Subject: [Python-checkins] [2 down, 63 flat] Results for Python (master branch) 2017-12-15 Message-ID: Results for project python/master, build date: 2017-12-15 03:03:37-08:00. - commit: 3325a67 - previous commit: 374c6e1 - revision date: 2017-12-15 12:35:48+02:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.857% | -0.467% | +6.013% | +6.600% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.868% | +1.419% | +25.221% | +8.056% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.378% | +0.360% | +26.038% | +7.062% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.655% | -0.076% | +23.493% | +6.902% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 1.842% | -4.684% | +5.489% | +14.951% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.769% | +0.736% | +9.767% | +13.408% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.650% | +0.185% | +6.403% | +10.150% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.482% | -1.717% | -0.546% | +7.121% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 1.147% | +0.560% | +12.479% | +15.593% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.567% | -1.117% | +13.815% | +14.762% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.402% | -0.425% | +4.266% | +6.989% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.367% | -1.412% | +4.560% | +5.179% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.697% | -0.886% | +1.903% | +7.737% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.175% | -1.383% | +13.115% | +9.079% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.494% | -0.845% | +8.812% | +9.184% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 1.005% | +0.192% | +7.199% | +11.003% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.655% | +0.159% | +10.911% | +10.567% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.396% | +0.650% | +8.160% | +9.223% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 0.903% | -0.358% | +2.725% | +9.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.265% | +1.522% | -0.212% | +12.633% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.305% | -2.940% | +6.859% | +14.446% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.663% | +1.500% | +47.084% | +11.713% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.433% | -2.926% | +7.538% | +15.744% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.360% | +0.138% | +18.003% | +13.195% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.832% | +0.934% | +8.920% | +8.963% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 3.673% | -1.962% | +4.765% | +4.091% | +-----+------------------------+--------+------------+------------+------------+ | :-( | nbody| 0.633% | -3.597% | -2.833% | +3.848% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.623% | -1.358% | +4.070% | +4.778% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.616% | +0.020% | +6.355% | +7.560% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.478% | -0.113% | +1.536% | +20.197% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.286% | -1.234% | +0.792% | +23.491% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.641% | -0.324% | +2.352% | +22.089% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 1.126% | +2.078% | +11.464% | +8.359% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.150% | -0.011% | +0.239% | +9.084% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.159% | -0.054% | +9.855% | +5.686% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.123% | +0.032% | +1.003% | +5.722% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.103% | -0.828% | +9.652% | +13.479% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.591% | -0.960% | +2.219% | +8.058% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.690% | -1.912% | -2.455% | +12.113% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.590% | -1.476% | -3.769% | +4.590% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 0.840% | -0.819% | +3.930% | +9.491% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.246% | +0.755% | +8.453% | +15.343% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.680% | -2.025% | -3.815% | +4.115% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.804% | -1.173% | +26.757% | +9.634% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.025% | -1.610% | +3.626% | +1.199% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.679% | -0.641% | +14.148% | +7.972% | +-----+------------------------+--------+------------+------------+------------+ | :-( | scimark_sparse_mat_mult| 0.421% | -4.745% | -5.836% | +4.081% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.430% | +0.371% | +3.744% | +5.234% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.521% | -1.020% | +7.116% | +5.813% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.272% | -1.322% | +6.202% | +5.093% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 5.966% | +1.526% | +19.182% | +7.266% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.416% | +0.163% | +11.455% | +8.144% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.865% | +0.592% | +9.197% | +6.740% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.130% | -1.047% | +10.912% | +8.815% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.852% | -3.138% | +9.382% | +11.243% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.990% | -1.502% | +18.462% | +11.972% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.045% | -0.395% | +5.937% | +4.728% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.302% | -0.045% | +2.074% | -0.335% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 3.463% | +0.199% | +7.918% | +19.494% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.573% | -0.244% | -1.042% | +16.774% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.483% | +0.709% | +7.638% | +7.911% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.951% | +0.042% | +5.597% | +9.434% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 3.055% | -1.331% | +1.379% | +10.345% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.897% | -1.014% | -7.898% | +12.718% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.357% | +1.007% | +7.190% | +9.138% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/2-down-63-flat-results-for-python-master-branch-2017-12-15 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Fri Dec 15 21:53:12 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 16 Dec 2017 02:53:12 -0000 Subject: [Python-checkins] bpo-27456: Ensure TCP_NODELAY is set on linux (#4231) (#4898) Message-ID: https://github.com/python/cpython/commit/572636d42566da8eb6e85d5b8164e9ed8860a255 commit: 572636d42566da8eb6e85d5b8164e9ed8860a255 branch: 3.6 author: Yury Selivanov committer: GitHub date: 2017-12-15T21:53:08-05:00 summary: bpo-27456: Ensure TCP_NODELAY is set on linux (#4231) (#4898) (cherry picked from commit e796b2fe26f220107ac50667de6cc86c82b465e3) files: A Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst M Lib/asyncio/base_events.py M Lib/asyncio/selector_events.py M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 8cc655c79f8..90757db41c6 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -84,18 +84,24 @@ def _set_reuseport(sock): 'SO_REUSEPORT defined but not implemented.') -def _is_stream_socket(sock): - # Linux's socket.type is a bitmask that can include extra info - # about socket, therefore we can't do simple - # `sock_type == socket.SOCK_STREAM`. - return (sock.type & socket.SOCK_STREAM) == socket.SOCK_STREAM +def _is_stream_socket(sock_type): + if hasattr(socket, 'SOCK_NONBLOCK'): + # Linux's socket.type is a bitmask that can include extra info + # about socket (like SOCK_NONBLOCK bit), therefore we can't do simple + # `sock_type == socket.SOCK_STREAM`, see + # https://github.com/torvalds/linux/blob/v4.13/include/linux/net.h#L77 + # for more details. + return (sock_type & 0xF) == socket.SOCK_STREAM + else: + return sock_type == socket.SOCK_STREAM -def _is_dgram_socket(sock): - # Linux's socket.type is a bitmask that can include extra info - # about socket, therefore we can't do simple - # `sock_type == socket.SOCK_DGRAM`. - return (sock.type & socket.SOCK_DGRAM) == socket.SOCK_DGRAM +def _is_dgram_socket(sock_type): + if hasattr(socket, 'SOCK_NONBLOCK'): + # See the comment in `_is_stream_socket`. + return (sock_type & 0xF) == socket.SOCK_DGRAM + else: + return sock_type == socket.SOCK_DGRAM def _ipaddr_info(host, port, family, type, proto): @@ -108,14 +114,9 @@ def _ipaddr_info(host, port, family, type, proto): host is None: return None - if type == socket.SOCK_STREAM: - # Linux only: - # getaddrinfo() can raise when socket.type is a bit mask. - # So if socket.type is a bit mask of SOCK_STREAM, and say - # SOCK_NONBLOCK, we simply return None, which will trigger - # a call to getaddrinfo() letting it process this request. + if _is_stream_socket(type): proto = socket.IPPROTO_TCP - elif type == socket.SOCK_DGRAM: + elif _is_dgram_socket(type): proto = socket.IPPROTO_UDP else: return None @@ -789,7 +790,7 @@ def create_connection(self, protocol_factory, host=None, port=None, *, if sock is None: raise ValueError( 'host and port was not specified and no sock specified') - if not _is_stream_socket(sock): + if not _is_stream_socket(sock.type): # We allow AF_INET, AF_INET6, AF_UNIX as long as they # are SOCK_STREAM. # We support passing AF_UNIX sockets even though we have @@ -841,7 +842,7 @@ def create_datagram_endpoint(self, protocol_factory, allow_broadcast=None, sock=None): """Create datagram connection.""" if sock is not None: - if not _is_dgram_socket(sock): + if not _is_dgram_socket(sock.type): raise ValueError( 'A UDP Socket was expected, got {!r}'.format(sock)) if (local_addr or remote_addr or @@ -1054,7 +1055,7 @@ def create_server(self, protocol_factory, host=None, port=None, else: if sock is None: raise ValueError('Neither host/port nor sock were specified') - if not _is_stream_socket(sock): + if not _is_stream_socket(sock.type): raise ValueError( 'A Stream Socket was expected, got {!r}'.format(sock)) sockets = [sock] @@ -1078,7 +1079,7 @@ def connect_accepted_socket(self, protocol_factory, sock, *, ssl=None): This method is a coroutine. When completed, the coroutine returns a (transport, protocol) pair. """ - if not _is_stream_socket(sock): + if not _is_stream_socket(sock.type): raise ValueError( 'A Stream Socket was expected, got {!r}'.format(sock)) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 942b627a1c1..aa65702f2db 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -43,7 +43,7 @@ def _test_selector_event(selector, fd, event): if hasattr(socket, 'TCP_NODELAY'): def _set_nodelay(sock): if (sock.family in {socket.AF_INET, socket.AF_INET6} and - sock.type == socket.SOCK_STREAM and + base_events._is_stream_socket(sock.type) and sock.proto == socket.IPPROTO_TCP): sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) else: diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 2806ea8dc90..5ea6c20c674 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -242,7 +242,7 @@ def create_unix_connection(self, protocol_factory, path, *, if sock is None: raise ValueError('no path and sock were specified') if (sock.family != socket.AF_UNIX or - not base_events._is_stream_socket(sock)): + not base_events._is_stream_socket(sock.type)): raise ValueError( 'A UNIX Domain Stream Socket was expected, got {!r}' .format(sock)) @@ -297,7 +297,7 @@ def create_unix_server(self, protocol_factory, path=None, *, 'path was not specified, and no sock specified') if (sock.family != socket.AF_UNIX or - not base_events._is_stream_socket(sock)): + not base_events._is_stream_socket(sock.type)): raise ValueError( 'A UNIX Domain Stream Socket was expected, got {!r}' .format(sock)) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 3f1ec651742..830f0d84a9d 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -116,13 +116,6 @@ def test_ipaddr_info(self): self.assertIsNone( base_events._ipaddr_info('::3%lo0', 1, INET6, STREAM, TCP)) - if hasattr(socket, 'SOCK_NONBLOCK'): - self.assertEqual( - None, - base_events._ipaddr_info( - '1.2.3.4', 1, INET, STREAM | socket.SOCK_NONBLOCK, TCP)) - - def test_port_parameter_types(self): # Test obscure kinds of arguments for "port". INET = socket.AF_INET diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 3477573ec3e..830b15c0893 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -17,6 +17,7 @@ from asyncio.selector_events import _SelectorSslTransport from asyncio.selector_events import _SelectorSocketTransport from asyncio.selector_events import _SelectorDatagramTransport +from asyncio.selector_events import _set_nodelay MOCK_ANY = mock.ANY @@ -1829,5 +1830,31 @@ def test_fatal_error_connected(self, m_exc): 'Fatal error on transport\nprotocol:.*\ntransport:.*'), exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY)) + +class TestSelectorUtils(test_utils.TestCase): + def check_set_nodelay(self, sock): + opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) + self.assertFalse(opt) + + _set_nodelay(sock) + + opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) + self.assertTrue(opt) + + @unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'), + 'need socket.TCP_NODELAY') + def test_set_nodelay(self): + sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, + proto=socket.IPPROTO_TCP) + with sock: + self.check_set_nodelay(sock) + + sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, + proto=socket.IPPROTO_TCP) + with sock: + sock.setblocking(False) + self.check_set_nodelay(sock) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst b/Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst new file mode 100644 index 00000000000..fa7b5616bb3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-02-11-57-41.bpo-27456.snzyTC.rst @@ -0,0 +1 @@ +Ensure TCP_NODELAY is set on Linux. Tests by Victor Stinner. From webhook-mailer at python.org Fri Dec 15 22:54:26 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Sat, 16 Dec 2017 03:54:26 -0000 Subject: [Python-checkins] bpo-29240, bpo-32030: Py_Main() re-reads config if encoding changes (#4899) Message-ID: https://github.com/python/cpython/commit/9454060e84a669dde63824d9e2fcaf295e34f687 commit: 9454060e84a669dde63824d9e2fcaf295e34f687 branch: master author: Victor Stinner committer: GitHub date: 2017-12-16T04:54:22+01:00 summary: bpo-29240, bpo-32030: Py_Main() re-reads config if encoding changes (#4899) bpo-29240, bpo-32030: If the encoding change (C locale coerced or UTF-8 Mode changed), Py_Main() now reads again the configuration with the new encoding. Changes: * Add _Py_UnixMain() called by main(). * Rename pymain_free_pymain() to pymain_clear_pymain(), it can now be called multipled times. * Rename pymain_parse_cmdline_envvars() to pymain_read_conf(). * Py_Main() now clears orig_argc and orig_argv at exit. * Remove argv_copy2, Py_Main() doesn't modify argv anymore. There is no need anymore to get two copies of the wchar_t** argv. * _PyCoreConfig: add coerce_c_locale and coerce_c_locale_warn. * Py_UTF8Mode is now initialized to -1. * Locale coercion (PEP 538) now respects -I and -E options. files: M Doc/using/cmdline.rst M Include/pylifecycle.h M Include/pystate.h M Lib/test/test_c_locale_coercion.py M Lib/test/test_cmd_line.py M Lib/test/test_utf8_mode.py M Modules/getpath.c M Modules/main.c M Programs/python.c M Python/bltinmodule.c M Python/fileutils.c M Python/pylifecycle.c diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 3915f336a5a..b1bd47fa6b9 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -779,9 +779,7 @@ conflict. If set to the value ``0``, causes the main Python command line application to skip coercing the legacy ASCII-based C locale to a more capable UTF-8 - based alternative. Note that this setting is checked even when the - :option:`-E` or :option:`-I` options are used, as it is handled prior to - the processing of command line options. + based alternative. If this variable is *not* set, or is set to a value other than ``0``, and the current locale reported for the ``LC_CTYPE`` category is the default diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index dcb7fcb8495..3ea8ad65088 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -105,6 +105,9 @@ PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *); /* Bootstrap __main__ (defined in Modules/main.c) */ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); +#ifdef Py_BUILD_CORE +PyAPI_FUNC(int) _Py_UnixMain(int argc, char **argv); +#endif /* In getpath.c */ PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void); @@ -194,7 +197,7 @@ PyAPI_FUNC(int) _PyOS_URandomNonblock(void *buffer, Py_ssize_t size); /* Legacy locale support */ #ifndef Py_LIMITED_API -PyAPI_FUNC(void) _Py_CoerceLegacyLocale(void); +PyAPI_FUNC(void) _Py_CoerceLegacyLocale(const _PyCoreConfig *config); PyAPI_FUNC(int) _Py_LegacyLocaleDetected(void); PyAPI_FUNC(char *) _Py_SetLocaleFromEnv(int category); #endif diff --git a/Include/pystate.h b/Include/pystate.h index a56c9b4ea6c..fff134a4970 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -38,7 +38,10 @@ typedef struct { int show_alloc_count; /* -X showalloccount */ int dump_refs; /* PYTHONDUMPREFS */ int malloc_stats; /* PYTHONMALLOCSTATS */ - int utf8_mode; /* -X utf8 or PYTHONUTF8 environment variable */ + int coerce_c_locale; /* PYTHONCOERCECLOCALE, -1 means unknown */ + int coerce_c_locale_warn; /* PYTHONCOERCECLOCALE=warn */ + int utf8_mode; /* -X utf8 or PYTHONUTF8 environment variable, + -1 means unknown */ wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ wchar_t *home; /* PYTHONHOME environment variable, @@ -46,7 +49,8 @@ typedef struct { wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ } _PyCoreConfig; -#define _PyCoreConfig_INIT (_PyCoreConfig){.use_hash_seed = -1} +#define _PyCoreConfig_INIT \ + (_PyCoreConfig){.use_hash_seed = -1, .coerce_c_locale = -1, .utf8_mode = -1} /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ /* Placeholders while working on the new configuration API diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index c0845d75a29..37dd834781c 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -65,7 +65,7 @@ def _set_locale_in_subprocess(locale_name): # If there's no valid CODESET, we expect coercion to be skipped cmd_fmt += "; import sys; sys.exit(not locale.nl_langinfo(locale.CODESET))" cmd = cmd_fmt.format(locale_name) - result, py_cmd = run_python_until_end("-c", cmd, __isolated=True) + result, py_cmd = run_python_until_end("-c", cmd, PYTHONCOERCECLOCALE='') return result.rc == 0 @@ -131,7 +131,6 @@ def get_child_details(cls, env_vars): """ result, py_cmd = run_python_until_end( "-X", "utf8=0", "-c", cls.CHILD_PROCESS_SCRIPT, - __isolated=True, **env_vars ) if not result.rc == 0: @@ -236,6 +235,7 @@ def test_external_target_locale_configuration(self): "LANG": "", "LC_CTYPE": "", "LC_ALL": "", + "PYTHONCOERCECLOCALE": "", } for env_var in ("LANG", "LC_CTYPE"): for locale_to_set in AVAILABLE_TARGETS: @@ -294,6 +294,7 @@ def _check_c_locale_coercion(self, "LANG": "", "LC_CTYPE": "", "LC_ALL": "", + "PYTHONCOERCECLOCALE": "", } base_var_dict.update(extra_vars) for env_var in ("LANG", "LC_CTYPE"): diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 2b14c301c7d..54ea3773a06 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -551,7 +551,7 @@ def test_xdev(self): self.assertEqual(out, "True") # Warnings - code = ("import sys, warnings; " + code = ("import warnings; " "print(' '.join('%s::%s' % (f[0], f[2].__name__) " "for f in warnings.filters))") if Py_DEBUG: diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py index 275a6ea8ed6..73d1bd424ca 100644 --- a/Lib/test/test_utf8_mode.py +++ b/Lib/test/test_utf8_mode.py @@ -7,6 +7,7 @@ import sys import textwrap import unittest +from test import support from test.support.script_helper import assert_python_ok, assert_python_failure @@ -14,9 +15,11 @@ class UTF8ModeTests(unittest.TestCase): - # Override PYTHONUTF8 and PYTHONLEGACYWINDOWSFSENCODING environment - # variables by default - DEFAULT_ENV = {'PYTHONUTF8': '', 'PYTHONLEGACYWINDOWSFSENCODING': ''} + DEFAULT_ENV = { + 'PYTHONUTF8': '', + 'PYTHONLEGACYWINDOWSFSENCODING': '', + 'PYTHONCOERCECLOCALE': '0', + } def posix_locale(self): loc = locale.setlocale(locale.LC_CTYPE, None) @@ -53,7 +56,7 @@ def test_xoption(self): self.assertEqual(out, '0') if MS_WINDOWS: - # PYTHONLEGACYWINDOWSFSENCODING disables the UTF-8 + # PYTHONLEGACYWINDOWSFSENCODING disables the UTF-8 Mode # and has the priority over -X utf8 out = self.get_output('-X', 'utf8', '-c', code, PYTHONLEGACYWINDOWSFSENCODING='1') @@ -201,6 +204,25 @@ def test_locale_getpreferredencoding(self): out = self.get_output('-X', 'utf8', '-c', code, LC_ALL='C') self.assertEqual(out, 'UTF-8 UTF-8') + @unittest.skipIf(MS_WINDOWS, 'test specific to Unix') + def test_cmd_line(self): + arg = 'h\xe9\u20ac'.encode('utf-8') + arg_utf8 = arg.decode('utf-8') + arg_ascii = arg.decode('ascii', 'surrogateescape') + code = 'import locale, sys; print("%s:%s" % (locale.getpreferredencoding(), ascii(sys.argv[1:])))' + + def check(utf8_opt, expected, **kw): + out = self.get_output('-X', utf8_opt, '-c', code, arg, **kw) + args = out.partition(':')[2].rstrip() + self.assertEqual(args, ascii(expected), out) + + check('utf8', [arg_utf8]) + if sys.platform == 'darwin' or support.is_android: + c_arg = arg_utf8 + else: + c_arg = arg_ascii + check('utf8=0', [c_arg], LC_ALL='C') + if __name__ == "__main__": unittest.main() diff --git a/Modules/getpath.c b/Modules/getpath.c index 6208a17f02e..b4b33437b6f 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -112,7 +112,7 @@ extern "C" { #define DECODE_LOCALE_ERR(NAME, LEN) \ ((LEN) == (size_t)-2) \ - ? _Py_INIT_USER_ERR("cannot decode " #NAME) \ + ? _Py_INIT_USER_ERR("cannot decode " NAME) \ : _Py_INIT_NO_MEMORY() typedef struct { diff --git a/Modules/main.c b/Modules/main.c index 6b602cf9b77..00de7f0d181 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -38,14 +38,14 @@ extern "C" { #define DECODE_LOCALE_ERR(NAME, LEN) \ (((LEN) == -2) \ - ? _Py_INIT_USER_ERR("cannot decode " #NAME) \ + ? _Py_INIT_USER_ERR("cannot decode " NAME) \ : _Py_INIT_NO_MEMORY()) #define SET_DECODE_ERROR(NAME, LEN) \ do { \ if ((LEN) == (size_t)-2) { \ - pymain->err = _Py_INIT_USER_ERR("cannot decode " #NAME); \ + pymain->err = _Py_INIT_USER_ERR("cannot decode " NAME); \ } \ else { \ pymain->err = _Py_INIT_NO_MEMORY(); \ @@ -53,8 +53,8 @@ extern "C" { } while (0) /* For Py_GetArgcArgv(); set by main() */ -static wchar_t **orig_argv; -static int orig_argc; +static wchar_t **orig_argv = NULL; +static int orig_argc = 0; /* command line options */ #define BASE_OPTS L"bBc:dEhiIJm:OqRsStuvVW:xX:?" @@ -427,8 +427,11 @@ typedef struct { _PyInitError err; /* PYTHONWARNINGS env var */ _Py_OptList env_warning_options; + int argc; wchar_t **argv; + int use_bytes_argv; + char **bytes_argv; int sys_argc; wchar_t **sys_argv; @@ -466,7 +469,6 @@ pymain_free_globals(_PyMain *pymain) { _PyPathConfig_Clear(&_Py_path_config); _PyImport_Fini2(); - _PyCoreConfig_Clear(&pymain->core_config); #ifdef __INSURE__ /* Insure++ is a memory analysis tool that aids in discovering @@ -483,22 +485,69 @@ pymain_free_globals(_PyMain *pymain) } +/* Clear argv allocated by pymain_decode_bytes_argv() */ +static void +pymain_clear_bytes_argv(_PyMain *pymain, int argc) +{ + if (pymain->use_bytes_argv && pymain->argv != NULL) { + for (int i = 0; i < argc; i++) { + PyMem_RawFree(pymain->argv[i]); + } + PyMem_RawFree(pymain->argv); + pymain->argv = NULL; + } +} + + +static int +pymain_decode_bytes_argv(_PyMain *pymain) +{ + assert(pymain->argv == NULL); + + /* +1 for a the NULL terminator */ + size_t size = sizeof(wchar_t*) * (pymain->argc + 1); + pymain->argv = (wchar_t **)PyMem_RawMalloc(size); + if (pymain->argv == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } + + for (int i = 0; i < pymain->argc; i++) { + size_t len; + pymain->argv[i] = Py_DecodeLocale(pymain->bytes_argv[i], &len); + if (pymain->argv[i] == NULL) { + pymain_clear_bytes_argv(pymain, i); + pymain->err = DECODE_LOCALE_ERR("command line arguments", + (Py_ssize_t)len); + return -1; + } + } + pymain->argv[pymain->argc] = NULL; + return 0; +} + + static void -pymain_free_pymain(_PyMain *pymain) +pymain_clear_pymain(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; pymain_optlist_clear(&cmdline->warning_options); pymain_optlist_clear(&cmdline->xoptions); PyMem_RawFree(cmdline->command); + cmdline->command = NULL; PyMem_RawFree(pymain->sys_argv); + pymain->sys_argv = NULL; pymain_optlist_clear(&pymain->env_warning_options); + pymain_clear_bytes_argv(pymain, pymain->argc); + + _PyCoreConfig_Clear(&pymain->core_config); } /* Clear Python ojects */ static void -pymain_free_python(_PyMain *pymain) +pymain_clear_python(_PyMain *pymain) { Py_CLEAR(pymain->main_importer_path); @@ -509,12 +558,12 @@ pymain_free_python(_PyMain *pymain) static void pymain_free(_PyMain *pymain) { - /* Force the allocator used by pymain_parse_cmdline_envvars() */ + /* Force the allocator used by pymain_read_conf() */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - pymain_free_python(pymain); - pymain_free_pymain(pymain); + pymain_clear_python(pymain); + pymain_clear_pymain(pymain); pymain_free_globals(pymain); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); @@ -743,6 +792,9 @@ pymain_parse_cmdline_impl(_PyMain *pymain) cmdline->filename = pymain->argv[_PyOS_optind]; } + pymain->run_code = (cmdline->command != NULL || cmdline->filename != NULL + || cmdline->module != NULL); + /* -c and -m options are exclusive */ assert(!(cmdline->command != NULL && cmdline->module != NULL)); @@ -1434,8 +1486,6 @@ pymain_repl(_PyMain *pymain) static int pymain_parse_cmdline(_PyMain *pymain) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - int res = pymain_parse_cmdline_impl(pymain); if (res < 0) { return -1; @@ -1446,21 +1496,6 @@ pymain_parse_cmdline(_PyMain *pymain) return 1; } - if (cmdline->print_help) { - pymain_usage(0, pymain->argv[0]); - pymain->status = 0; - return 1; - } - - if (cmdline->print_version) { - printf("Python %s\n", - (cmdline->print_version >= 2) ? Py_GetVersion() : PY_VERSION); - return 1; - } - - pymain->run_code = (cmdline->command != NULL || cmdline->filename != NULL - || cmdline->module != NULL); - return 0; } @@ -1852,6 +1887,19 @@ pymain_parse_envvars(_PyMain *pymain) pymain->core_config.malloc_stats = 1; } + const char* env = pymain_get_env_var("PYTHONCOERCECLOCALE"); + if (env) { + if (strcmp(env, "0") == 0) { + pymain->core_config.coerce_c_locale = 0; + } + else if (strcmp(env, "warn") == 0) { + pymain->core_config.coerce_c_locale_warn = 1; + } + else { + pymain->core_config.coerce_c_locale = 1; + } + } + if (pymain_init_utf8_mode(pymain) < 0) { return -1; } @@ -1867,23 +1915,19 @@ pymain_parse_envvars(_PyMain *pymain) Return 1 if Python is done and must exit. Set pymain->err and return -1 on error. */ static int -pymain_parse_cmdline_envvars_impl(_PyMain *pymain) +pymain_read_conf_impl(_PyMain *pymain) { int res = pymain_parse_cmdline(pymain); - if (res < 0) { - return -1; - } - if (res > 0) { - return 1; + if (res != 0) { + return res; } - /* Set Py_IgnoreEnvironmentFlag needed by Py_GETENV() */ - pymain_set_global_config(pymain); + /* Set Py_IgnoreEnvironmentFlag for Py_GETENV() */ + Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; if (pymain_parse_envvars(pymain) < 0) { return -1; } - /* FIXME: if utf8_mode value changed, parse again cmdline */ if (pymain_init_sys_argv(pymain) < 0) { return -1; @@ -1899,14 +1943,101 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) static int -pymain_parse_cmdline_envvars(_PyMain *pymain) +pymain_read_conf(_PyMain *pymain) { + int res = -1; + /* Force default allocator, since pymain_free() must use the same allocator than this function. */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - int res = pymain_parse_cmdline_envvars_impl(pymain); + char *oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); + if (oldloc == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + goto done; + } + + /* Reconfigure the locale to the default for this process */ + _Py_SetLocaleFromEnv(LC_ALL); + + int locale_coerced = 0; + int loops = 0; + int init_ignore_env = pymain->core_config.ignore_environment; + + while (1) { + int utf8_mode = pymain->core_config.utf8_mode; + int encoding_changed = 0; + + /* Watchdog to prevent an infinite loop */ + loops++; + if (loops == 3) { + pymain->err = _Py_INIT_ERR("Encoding changed twice while " + "reading the configuration"); + goto done; + } + + if (pymain->use_bytes_argv) { + if (pymain_decode_bytes_argv(pymain) < 0) { + goto done; + } + } + + res = pymain_read_conf_impl(pymain); + if (res != 0) { + goto done; + } + + /* The legacy C locale assumes ASCII as the default text encoding, which + * causes problems not only for the CPython runtime, but also other + * components like GNU readline. + * + * Accordingly, when the CLI detects it, it attempts to coerce it to a + * more capable UTF-8 based alternative. + * + * See the documentation of the PYTHONCOERCECLOCALE setting for more + * details. + */ + if (pymain->core_config.coerce_c_locale == 1 && !locale_coerced) { + locale_coerced = 1; + _Py_CoerceLegacyLocale(&pymain->core_config); + encoding_changed = 1; + } + + if (utf8_mode == -1) { + if (pymain->core_config.utf8_mode == 1) { + /* UTF-8 Mode enabled */ + encoding_changed = 1; + } + } + else { + if (pymain->core_config.utf8_mode != utf8_mode) { + encoding_changed = 1; + } + } + + if (!encoding_changed) { + break; + } + + /* Reset the configuration, except UTF-8 Mode. Set Py_UTF8Mode for + Py_DecodeLocale(). Reset Py_IgnoreEnvironmentFlag, modified by + pymain_read_conf_impl(). */ + Py_UTF8Mode = pymain->core_config.utf8_mode; + Py_IgnoreEnvironmentFlag = init_ignore_env; + pymain_clear_pymain(pymain); + pymain_get_global_config(pymain); + + /* The encoding changed: read again the configuration + with the new encoding */ + } + res = 0; + +done: + if (oldloc != NULL) { + setlocale(LC_ALL, oldloc); + PyMem_RawFree(oldloc); + } PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return res; @@ -1940,6 +2071,24 @@ _PyCoreConfig_Read(_PyCoreConfig *config) } } + if (config->utf8_mode < 0 || config->coerce_c_locale < 0) { + if (_Py_LegacyLocaleDetected()) { + if (config->utf8_mode < 0) { + config->utf8_mode = 1; + } + if (config->coerce_c_locale < 0) { + config->coerce_c_locale = 1; + } + } + + if (config->coerce_c_locale < 0) { + config->coerce_c_locale = 0; + } + if (config->utf8_mode < 0) { + config->utf8_mode = 0; + } + } + return _Py_INIT_OK(); } @@ -2247,17 +2396,24 @@ pymain_run_python(_PyMain *pymain) static int pymain_init(_PyMain *pymain) { + /* 754 requires that FP exceptions run in "no stop" mode by default, + * and until C vendors implement C99's ways to control FP exceptions, + * Python requires non-stop mode. Alas, some platforms enable FP + * exceptions by default. Here we disable them. + */ +#ifdef __FreeBSD__ + fedisableexcept(FE_OVERFLOW); +#endif + pymain->err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(pymain->err)) { return -1; } - pymain->core_config.utf8_mode = Py_UTF8Mode; pymain->core_config._disable_importlib = 0; pymain->config.install_signal_handlers = 1; - orig_argc = pymain->argc; /* For Py_GetArgcArgv() */ - orig_argv = pymain->argv; + pymain_get_global_config(pymain); return 0; } @@ -2265,14 +2421,13 @@ pymain_init(_PyMain *pymain) static int pymain_impl(_PyMain *pymain) { - int res = pymain_init(pymain); - if (res < 0) { + if (pymain_init(pymain) < 0) { return -1; } - pymain_get_global_config(pymain); - - res = pymain_parse_cmdline_envvars(pymain); + /* Read the configuration, but initialize also the LC_CTYPE locale: + enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */ + int res = pymain_read_conf(pymain); if (res < 0) { return -1; } @@ -2281,6 +2436,21 @@ pymain_impl(_PyMain *pymain) return 0; } + _Py_CommandLineDetails *cmdline = &pymain->cmdline; + if (cmdline->print_help) { + pymain_usage(0, pymain->argv[0]); + return 0; + } + + if (cmdline->print_version) { + printf("Python %s\n", + (cmdline->print_version >= 2) ? Py_GetVersion() : PY_VERSION); + return 0; + } + + orig_argc = pymain->argc; /* For Py_GetArgcArgv() */ + orig_argv = pymain->argv; + res = pymain_init_python_core(pymain); if (res < 0) { return -1; @@ -2293,7 +2463,7 @@ pymain_impl(_PyMain *pymain) pymain_run_python(pymain); - pymain_free_python(pymain); + pymain_clear_python(pymain); if (Py_FinalizeEx() < 0) { /* Value unlikely to be confused with a non-error exit status or @@ -2304,22 +2474,46 @@ pymain_impl(_PyMain *pymain) } +static int +pymain_main(_PyMain *pymain) +{ + memset(&pymain->cmdline, 0, sizeof(pymain->cmdline)); + + if (pymain_impl(pymain) < 0) { + _Py_FatalInitError(pymain->err); + } + pymain_free(pymain); + + orig_argc = 0; + orig_argv = NULL; + + return pymain->status; +} + + int Py_Main(int argc, wchar_t **argv) { _PyMain pymain = _PyMain_INIT; - memset(&pymain.cmdline, 0, sizeof(pymain.cmdline)); pymain.argc = argc; pymain.argv = argv; - if (pymain_impl(&pymain) < 0) { - _Py_FatalInitError(pymain.err); - } - pymain_free(&pymain); + return pymain_main(&pymain); +} + + +int +_Py_UnixMain(int argc, char **argv) +{ + _PyMain pymain = _PyMain_INIT; + pymain.argc = argc; + pymain.use_bytes_argv = 1; + pymain.bytes_argv = argv; - return pymain.status; + return pymain_main(&pymain); } + /* this is gonna seem *real weird*, but if you put some other code between Py_Main() and Py_GetArgcArgv() you will need to adjust the test in the while statement in Misc/gdbinit:ppystack */ diff --git a/Programs/python.c b/Programs/python.c index aef7122517a..a295486d73f 100644 --- a/Programs/python.c +++ b/Programs/python.c @@ -17,98 +17,9 @@ wmain(int argc, wchar_t **argv) #else -static void _Py_NO_RETURN -fatal_error(const char *msg) -{ - fprintf(stderr, "Fatal Python error: %s\n", msg); - fflush(stderr); - exit(1); -} - - int main(int argc, char **argv) { - wchar_t **argv_copy; - /* We need a second copy, as Python might modify the first one. */ - wchar_t **argv_copy2; - int i, status; - char *oldloc; - - _PyInitError err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - fatal_error(err.msg); - } - - /* Force default allocator, to be able to release memory above - with a known allocator. */ - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, NULL); - - argv_copy = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1)); - argv_copy2 = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1)); - if (!argv_copy || !argv_copy2) { - fatal_error("out of memory"); - return 1; - } - - /* 754 requires that FP exceptions run in "no stop" mode by default, - * and until C vendors implement C99's ways to control FP exceptions, - * Python requires non-stop mode. Alas, some platforms enable FP - * exceptions by default. Here we disable them. - */ -#ifdef __FreeBSD__ - fedisableexcept(FE_OVERFLOW); -#endif - - oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); - if (!oldloc) { - fatal_error("out of memory"); - return 1; - } - - /* Reconfigure the locale to the default for this process */ - _Py_SetLocaleFromEnv(LC_ALL); - - /* The legacy C locale assumes ASCII as the default text encoding, which - * causes problems not only for the CPython runtime, but also other - * components like GNU readline. - * - * Accordingly, when the CLI detects it, it attempts to coerce it to a - * more capable UTF-8 based alternative. - * - * See the documentation of the PYTHONCOERCECLOCALE setting for more - * details. - */ - if (_Py_LegacyLocaleDetected()) { - Py_UTF8Mode = 1; - _Py_CoerceLegacyLocale(); - } - - /* Convert from char to wchar_t based on the locale settings */ - for (i = 0; i < argc; i++) { - argv_copy[i] = Py_DecodeLocale(argv[i], NULL); - if (!argv_copy[i]) { - PyMem_RawFree(oldloc); - fatal_error("unable to decode the command line arguments"); - } - argv_copy2[i] = argv_copy[i]; - } - argv_copy2[argc] = argv_copy[argc] = NULL; - - setlocale(LC_ALL, oldloc); - PyMem_RawFree(oldloc); - - status = Py_Main(argc, argv_copy); - - /* Py_Main() can change PyMem_RawMalloc() allocator, so restore the default - to release memory blocks allocated before Py_Main() */ - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, NULL); - - for (i = 0; i < argc; i++) { - PyMem_RawFree(argv_copy2[i]); - } - PyMem_RawFree(argv_copy); - PyMem_RawFree(argv_copy2); - return status; + return _Py_UnixMain(argc, argv); } #endif diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 604493dc5e2..e702f7c6e9e 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -29,9 +29,10 @@ const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ int Py_HasFileSystemDefaultEncoding = 0; #endif const char *Py_FileSystemDefaultEncodeErrors = "surrogateescape"; -/* UTF-8 mode (PEP 540): if non-zero, use the UTF-8 encoding, and change stdin - and stdout error handler to "surrogateescape". */ -int Py_UTF8Mode = 0; +/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change + stdin and stdout error handler to "surrogateescape". It is equal to + -1 by default: unknown, will be set by Py_Main() */ +int Py_UTF8Mode = -1; _Py_IDENTIFIER(__builtins__); _Py_IDENTIFIER(__dict__); diff --git a/Python/fileutils.c b/Python/fileutils.c index 4b69049ce58..c4d495d0d63 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -393,7 +393,7 @@ Py_DecodeLocale(const char* arg, size_t *size) #if defined(__APPLE__) || defined(__ANDROID__) return _Py_DecodeUTF8_surrogateescape(arg, strlen(arg), size); #else - if (Py_UTF8Mode) { + if (Py_UTF8Mode == 1) { return _Py_DecodeUTF8_surrogateescape(arg, strlen(arg), size); } @@ -539,7 +539,7 @@ Py_EncodeLocale(const wchar_t *text, size_t *error_pos) #if defined(__APPLE__) || defined(__ANDROID__) return _Py_EncodeLocaleUTF8(text, error_pos); #else /* __APPLE__ */ - if (Py_UTF8Mode) { + if (Py_UTF8Mode == 1) { return _Py_EncodeLocaleUTF8(text, error_pos); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 8c626075d5d..6500995ee24 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -385,18 +385,10 @@ static const char *_C_LOCALE_WARNING = "C.utf8, or UTF-8 (if available) as alternative Unicode-compatible " "locales is recommended.\n"; -static int -_legacy_locale_warnings_enabled(void) -{ - const char *coerce_c_locale = getenv("PYTHONCOERCECLOCALE"); - return (coerce_c_locale != NULL && - strncmp(coerce_c_locale, "warn", 5) == 0); -} - static void -_emit_stderr_warning_for_legacy_locale(void) +_emit_stderr_warning_for_legacy_locale(const _PyCoreConfig *core_config) { - if (_legacy_locale_warnings_enabled()) { + if (core_config->coerce_c_locale_warn) { if (_Py_LegacyLocaleDetected()) { fprintf(stderr, "%s", _C_LOCALE_WARNING); } @@ -440,12 +432,12 @@ get_default_standard_stream_error_handler(void) } #ifdef PY_COERCE_C_LOCALE -static const char _C_LOCALE_COERCION_WARNING[] = +static const char C_LOCALE_COERCION_WARNING[] = "Python detected LC_CTYPE=C: LC_CTYPE coerced to %.20s (set another locale " "or PYTHONCOERCECLOCALE=0 to disable this locale coercion behavior).\n"; static void -_coerce_default_locale_settings(const _LocaleCoercionTarget *target) +_coerce_default_locale_settings(const _PyCoreConfig *config, const _LocaleCoercionTarget *target) { const char *newloc = target->locale_name; @@ -458,8 +450,8 @@ _coerce_default_locale_settings(const _LocaleCoercionTarget *target) "Error setting LC_CTYPE, skipping C locale coercion\n"); return; } - if (_legacy_locale_warnings_enabled()) { - fprintf(stderr, _C_LOCALE_COERCION_WARNING, newloc); + if (config->coerce_c_locale_warn) { + fprintf(stderr, C_LOCALE_COERCION_WARNING, newloc); } /* Reconfigure with the overridden environment variables */ @@ -468,47 +460,31 @@ _coerce_default_locale_settings(const _LocaleCoercionTarget *target) #endif void -_Py_CoerceLegacyLocale(void) +_Py_CoerceLegacyLocale(const _PyCoreConfig *config) { #ifdef PY_COERCE_C_LOCALE - /* We ignore the Python -E and -I flags here, as the CLI needs to sort out - * the locale settings *before* we try to do anything with the command - * line arguments. For cross-platform debugging purposes, we also need - * to give end users a way to force even scripts that are otherwise - * isolated from their environment to use the legacy ASCII-centric C - * locale. - * - * Ignoring -E and -I is safe from a security perspective, as we only use - * the setting to turn *off* the implicit locale coercion, and anyone with - * access to the process environment already has the ability to set - * `LC_ALL=C` to override the C level locale settings anyway. - */ - const char *coerce_c_locale = getenv("PYTHONCOERCECLOCALE"); - if (coerce_c_locale == NULL || strncmp(coerce_c_locale, "0", 2) != 0) { - /* PYTHONCOERCECLOCALE is not set, or is set to something other than "0" */ - const char *locale_override = getenv("LC_ALL"); - if (locale_override == NULL || *locale_override == '\0') { - /* LC_ALL is also not set (or is set to an empty string) */ - const _LocaleCoercionTarget *target = NULL; - for (target = _TARGET_LOCALES; target->locale_name; target++) { - const char *new_locale = setlocale(LC_CTYPE, - target->locale_name); - if (new_locale != NULL) { + const char *locale_override = getenv("LC_ALL"); + if (locale_override == NULL || *locale_override == '\0') { + /* LC_ALL is also not set (or is set to an empty string) */ + const _LocaleCoercionTarget *target = NULL; + for (target = _TARGET_LOCALES; target->locale_name; target++) { + const char *new_locale = setlocale(LC_CTYPE, + target->locale_name); + if (new_locale != NULL) { #if !defined(__APPLE__) && !defined(__ANDROID__) && \ - defined(HAVE_LANGINFO_H) && defined(CODESET) - /* Also ensure that nl_langinfo works in this locale */ - char *codeset = nl_langinfo(CODESET); - if (!codeset || *codeset == '\0') { - /* CODESET is not set or empty, so skip coercion */ - new_locale = NULL; - _Py_SetLocaleFromEnv(LC_CTYPE); - continue; - } -#endif - /* Successfully configured locale, so make it the default */ - _coerce_default_locale_settings(target); - return; +defined(HAVE_LANGINFO_H) && defined(CODESET) + /* Also ensure that nl_langinfo works in this locale */ + char *codeset = nl_langinfo(CODESET); + if (!codeset || *codeset == '\0') { + /* CODESET is not set or empty, so skip coercion */ + new_locale = NULL; + _Py_SetLocaleFromEnv(LC_CTYPE); + continue; } +#endif + /* Successfully configured locale, so make it the default */ + _coerce_default_locale_settings(config, target); + return; } } } @@ -648,7 +624,7 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) the locale's charset without having to switch locales. */ _Py_SetLocaleFromEnv(LC_CTYPE); - _emit_stderr_warning_for_legacy_locale(); + _emit_stderr_warning_for_legacy_locale(core_config); #endif err = _Py_HashRandomization_Init(core_config); From webhook-mailer at python.org Sat Dec 16 02:42:36 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 16 Dec 2017 07:42:36 -0000 Subject: [Python-checkins] fix up signedness in PyImport_ExtendInittab (#4831) Message-ID: https://github.com/python/cpython/commit/0c644fcda095b12eedfb417f15429795c09196b6 commit: 0c644fcda095b12eedfb417f15429795c09196b6 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-15T23:42:33-08:00 summary: fix up signedness in PyImport_ExtendInittab (#4831) As a result of 92a3c6f493ad411e4cf0acdf305ef4876aa90669, the compiler complains: Python/import.c:2311:21: warning: comparison of integers of different signs: 'long' and 'unsigned long' [-Wsign-compare] if ((i + n + 1) <= PY_SSIZE_T_MAX / sizeof(struct _inittab)) { ~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This overflow is extremely unlikely to happen, but let's avoid undefined behavior anyway. files: M Python/import.c diff --git a/Python/import.c b/Python/import.c index d5dad1a6a30..8d306403a29 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2291,7 +2291,7 @@ int PyImport_ExtendInittab(struct _inittab *newtab) { struct _inittab *p; - Py_ssize_t i, n; + size_t i, n; int res = 0; /* Count the number of entries in both tables */ @@ -2308,13 +2308,11 @@ PyImport_ExtendInittab(struct _inittab *newtab) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); /* Allocate new memory for the combined table */ - if ((i + n + 1) <= PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(struct _inittab)) { + p = NULL; + if (i + n <= SIZE_MAX / sizeof(struct _inittab) - 1) { size_t size = sizeof(struct _inittab) * (i + n + 1); p = PyMem_RawRealloc(inittab_copy, size); } - else { - p = NULL; - } if (p == NULL) { res = -1; goto done; From webhook-mailer at python.org Sat Dec 16 03:51:24 2017 From: webhook-mailer at python.org (Nick Coghlan) Date: Sat, 16 Dec 2017 08:51:24 -0000 Subject: [Python-checkins] bpo-32002: Refactor C locale coercion tests (GH-4369) Message-ID: https://github.com/python/cpython/commit/9c19b020249c451891affd81751947321a1e6957 commit: 9c19b020249c451891affd81751947321a1e6957 branch: master author: Nick Coghlan committer: GitHub date: 2017-12-16T21:51:19+13:00 summary: bpo-32002: Refactor C locale coercion tests (GH-4369) Exactly which locale requests will end up giving you the "C" locale is actually platform dependent. A blank locale and "POSIX" will translate to "C" on most Linux distros, but may not do so on other platforms, so this adjusts the way the tests are structured to better account for that. This is an initial step towards fixing the current test failure on Cygwin (hence the issue reference) files: A Misc/NEWS.d/next/Tests/2017-11-11-16-35-18.bpo-32002.itDxIo.rst M Lib/test/test_c_locale_coercion.py diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 37dd834781c..1db293b9c37 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -14,30 +14,51 @@ interpreter_requires_environment, ) +# Set the list of ways we expect to be able to ask for the "C" locale +EXPECTED_C_LOCALE_EQUIVALENTS = ["C", "invalid.ascii"] + # Set our expectation for the default encoding used in the C locale # for the filesystem encoding and the standard streams - -# While most *nix platforms default to ASCII in the C locale, some use a -# different encoding. -if sys.platform.startswith("aix"): - C_LOCALE_STREAM_ENCODING = "iso8859-1" -elif test.support.is_android: - C_LOCALE_STREAM_ENCODING = "utf-8" -else: - C_LOCALE_STREAM_ENCODING = "ascii" - -# FS encoding is UTF-8 on macOS, other *nix platforms use the locale encoding -if sys.platform == "darwin": - C_LOCALE_FS_ENCODING = "utf-8" -else: - C_LOCALE_FS_ENCODING = C_LOCALE_STREAM_ENCODING - -# Note that the above is probably still wrong in some cases, such as: +EXPECTED_C_LOCALE_STREAM_ENCODING = "ascii" +EXPECTED_C_LOCALE_FS_ENCODING = "ascii" + +# Set our expectation for the default locale used when none is specified +EXPECT_COERCION_IN_DEFAULT_LOCALE = True + +# Apply some platform dependent overrides +if sys.platform.startswith("linux"): + if test.support.is_android: + # Android defaults to using UTF-8 for all system interfaces + EXPECTED_C_LOCALE_STREAM_ENCODING = "utf-8" + EXPECTED_C_LOCALE_FS_ENCODING = "utf-8" + else: + # Linux distros typically alias the POSIX locale directly to the C + # locale. + # TODO: Once https://bugs.python.org/issue30672 is addressed, we'll be + # able to check this case unconditionally + EXPECTED_C_LOCALE_EQUIVALENTS.append("POSIX") +elif sys.platform.startswith("aix"): + # AIX uses iso8859-1 in the C locale, other *nix platforms use ASCII + EXPECTED_C_LOCALE_STREAM_ENCODING = "iso8859-1" + EXPECTED_C_LOCALE_FS_ENCODING = "iso8859-1" +elif sys.platform == "darwin": + # FS encoding is UTF-8 on macOS + EXPECTED_C_LOCALE_FS_ENCODING = "utf-8" +elif sys.platform == "cygwin": + # Cygwin defaults to using C.UTF-8 + # TODO: Work out a robust dynamic test for this that doesn't rely on + # CPython's own locale handling machinery + EXPECT_COERCION_IN_DEFAULT_LOCALE = False + +# Note that the above expectations are still wrong in some cases, such as: # * Windows when PYTHONLEGACYWINDOWSFSENCODING is set -# * AIX and any other platforms that use latin-1 in the C locale +# * Any platform other than AIX that uses latin-1 in the C locale +# * Any Linux distro where POSIX isn't a simple alias for the C locale +# * Any Linux distro where the default locale is something other than "C" # # Options for dealing with this: -# * Don't set PYTHON_COERCE_C_LOCALE on such platforms (e.g. Windows doesn't) +# * Don't set the PY_COERCE_C_LOCALE preprocessor definition on +# such platforms (e.g. it isn't set on Windows) # * Fix the test expectations to match the actual platform behaviour # In order to get the warning messages to match up as expected, the candidate @@ -47,7 +68,7 @@ # There's no reliable cross-platform way of checking locale alias # lists, so the only way of knowing which of these locales will work # is to try them with locale.setlocale(). We do that in a subprocess -# to avoid altering the locale of the test runner. +# in setUpModule() below to avoid altering the locale of the test runner. # # If the relevant locale module attributes exist, and we're not on a platform # where we expect it to always succeed, we also check that @@ -216,8 +237,9 @@ def _check_child_encoding_details(self, class LocaleConfigurationTests(_LocaleHandlingTestCase): # Test explicit external configuration via the process environment - def setUpClass(): - # This relies on setupModule() having been run, so it can't be + @classmethod + def setUpClass(cls): + # This relies on setUpModule() having been run, so it can't be # handled via the @unittest.skipUnless decorator if not AVAILABLE_TARGETS: raise unittest.SkipTest("No C-with-UTF-8 locale available") @@ -284,8 +306,8 @@ def _check_c_locale_coercion(self, if not AVAILABLE_TARGETS: # Locale coercion is disabled when there aren't any target locales - fs_encoding = C_LOCALE_FS_ENCODING - stream_encoding = C_LOCALE_STREAM_ENCODING + fs_encoding = EXPECTED_C_LOCALE_FS_ENCODING + stream_encoding = EXPECTED_C_LOCALE_STREAM_ENCODING coercion_expected = False if expected_warnings: expected_warnings = [LEGACY_LOCALE_WARNING] @@ -297,41 +319,47 @@ def _check_c_locale_coercion(self, "PYTHONCOERCECLOCALE": "", } base_var_dict.update(extra_vars) - for env_var in ("LANG", "LC_CTYPE"): - for locale_to_set in ("", "C", "POSIX", "invalid.ascii"): - # XXX (ncoghlan): *BSD platforms don't behave as expected in the - # POSIX locale, so we skip that for now - # See https://bugs.python.org/issue30672 for discussion - if locale_to_set == "POSIX": - continue + if coerce_c_locale is not None: + base_var_dict["PYTHONCOERCECLOCALE"] = coerce_c_locale - # Platforms using UTF-8 in the C locale do not print - # CLI_COERCION_WARNING when all the locale envt variables are - # not set or set to the empty string. + # Check behaviour for the default locale + with self.subTest(default_locale=True, + PYTHONCOERCECLOCALE=coerce_c_locale): + if EXPECT_COERCION_IN_DEFAULT_LOCALE: _expected_warnings = expected_warnings - for _env_var in base_var_dict: - if base_var_dict[_env_var]: - break - else: - if (C_LOCALE_STREAM_ENCODING == "utf-8" and - locale_to_set == "" and coerce_c_locale == "warn"): - _expected_warnings = None - + _coercion_expected = coercion_expected + else: + _expected_warnings = None + _coercion_expected = False + # On Android CLI_COERCION_WARNING is not printed when all the + # locale environment variables are undefined or empty. When + # this code path is run with environ['LC_ALL'] == 'C', then + # LEGACY_LOCALE_WARNING is printed. + if (test.support.is_android and + _expected_warnings == [CLI_COERCION_WARNING]): + _expected_warnings = None + self._check_child_encoding_details(base_var_dict, + fs_encoding, + stream_encoding, + _expected_warnings, + _coercion_expected) + + # Check behaviour for explicitly configured locales + for locale_to_set in EXPECTED_C_LOCALE_EQUIVALENTS: + for env_var in ("LANG", "LC_CTYPE"): with self.subTest(env_var=env_var, nominal_locale=locale_to_set, PYTHONCOERCECLOCALE=coerce_c_locale): var_dict = base_var_dict.copy() var_dict[env_var] = locale_to_set - if coerce_c_locale is not None: - var_dict["PYTHONCOERCECLOCALE"] = coerce_c_locale # Check behaviour on successful coercion self._check_child_encoding_details(var_dict, fs_encoding, stream_encoding, - _expected_warnings, + expected_warnings, coercion_expected) - def test_test_PYTHONCOERCECLOCALE_not_set(self): + def test_PYTHONCOERCECLOCALE_not_set(self): # This should coerce to the first available target locale by default self._check_c_locale_coercion("utf-8", "utf-8", coerce_c_locale=None) @@ -350,27 +378,27 @@ def test_PYTHONCOERCECLOCALE_set_to_warn(self): def test_PYTHONCOERCECLOCALE_set_to_zero(self): # The setting "0" should result in the locale coercion being disabled - self._check_c_locale_coercion(C_LOCALE_FS_ENCODING, - C_LOCALE_STREAM_ENCODING, + self._check_c_locale_coercion(EXPECTED_C_LOCALE_FS_ENCODING, + EXPECTED_C_LOCALE_STREAM_ENCODING, coerce_c_locale="0", coercion_expected=False) # Setting LC_ALL=C shouldn't make any difference to the behaviour - self._check_c_locale_coercion(C_LOCALE_FS_ENCODING, - C_LOCALE_STREAM_ENCODING, + self._check_c_locale_coercion(EXPECTED_C_LOCALE_FS_ENCODING, + EXPECTED_C_LOCALE_STREAM_ENCODING, coerce_c_locale="0", LC_ALL="C", coercion_expected=False) def test_LC_ALL_set_to_C(self): # Setting LC_ALL should render the locale coercion ineffective - self._check_c_locale_coercion(C_LOCALE_FS_ENCODING, - C_LOCALE_STREAM_ENCODING, + self._check_c_locale_coercion(EXPECTED_C_LOCALE_FS_ENCODING, + EXPECTED_C_LOCALE_STREAM_ENCODING, coerce_c_locale=None, LC_ALL="C", coercion_expected=False) # And result in a warning about a lack of locale compatibility - self._check_c_locale_coercion(C_LOCALE_FS_ENCODING, - C_LOCALE_STREAM_ENCODING, + self._check_c_locale_coercion(EXPECTED_C_LOCALE_FS_ENCODING, + EXPECTED_C_LOCALE_STREAM_ENCODING, coerce_c_locale="warn", LC_ALL="C", expected_warnings=[LEGACY_LOCALE_WARNING], diff --git a/Misc/NEWS.d/next/Tests/2017-11-11-16-35-18.bpo-32002.itDxIo.rst b/Misc/NEWS.d/next/Tests/2017-11-11-16-35-18.bpo-32002.itDxIo.rst new file mode 100644 index 00000000000..9cc7ec22c45 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-11-11-16-35-18.bpo-32002.itDxIo.rst @@ -0,0 +1,2 @@ +Adjust C locale coercion testing for the empty locale and POSIX locale +cases to more readily adjust to platform dependent behaviour. From solipsis at pitrou.net Sat Dec 16 04:09:38 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 16 Dec 2017 09:09:38 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-2 Message-ID: <20171216090938.25917.E97CA85E8FFE8DC4@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 8, -7] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [2, -2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogGUeOEt', '--timeout', '7200'] From webhook-mailer at python.org Sat Dec 16 04:25:59 2017 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sat, 16 Dec 2017 09:25:59 -0000 Subject: [Python-checkins] Add tests for using PEP560 with classes implemented in C. (#4883) Message-ID: https://github.com/python/cpython/commit/45700fb757591a672e9d25b8252971c2a2caeaf2 commit: 45700fb757591a672e9d25b8252971c2a2caeaf2 branch: master author: Serhiy Storchaka committer: Ivan Levkivskyi date: 2017-12-16T10:25:56+01:00 summary: Add tests for using PEP560 with classes implemented in C. (#4883) Based on tests from #4878 files: M Lib/test/test_genericclass.py M Modules/_testcapimodule.c diff --git a/Lib/test/test_genericclass.py b/Lib/test/test_genericclass.py index 214527b01fa..2057fc000c0 100644 --- a/Lib/test/test_genericclass.py +++ b/Lib/test/test_genericclass.py @@ -1,4 +1,5 @@ import unittest +from test import support class TestMROEntry(unittest.TestCase): @@ -248,5 +249,22 @@ def __class_getitem__(cls, item): self.assertEqual(C[int], 'from metaclass') + at support.cpython_only +class CAPITest(unittest.TestCase): + + def test_c_class(self): + from _testcapi import Generic, GenericAlias + self.assertIsInstance(Generic.__class_getitem__(Generic, int), GenericAlias) + + IntGeneric = Generic[int] + self.assertIs(type(IntGeneric), GenericAlias) + self.assertEqual(IntGeneric.__mro_entries__(()), (int,)) + class C(IntGeneric): + pass + self.assertEqual(C.__bases__, (int,)) + self.assertEqual(C.__orig_bases__, (IntGeneric,)) + self.assertEqual(C.__mro__, (C, int, object)) + + if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 4bb3e82d1dc..47b50640f5d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5053,6 +5053,81 @@ recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds) } +/* Test PEP 560 */ + +typedef struct { + PyObject_HEAD + PyObject *item; +} PyGenericAliasObject; + +static void +generic_alias_dealloc(PyGenericAliasObject *self) +{ + Py_CLEAR(self->item); +} + +static PyObject * +generic_alias_mro_entries(PyGenericAliasObject *self, PyObject *bases) +{ + return PyTuple_Pack(1, self->item); +} + +static PyMethodDef generic_alias_methods[] = { + {"__mro_entries__", (PyCFunction) generic_alias_mro_entries, METH_O, NULL}, + {NULL} /* sentinel */ +}; + +PyTypeObject GenericAlias_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GenericAlias", + sizeof(PyGenericAliasObject), + 0, + .tp_dealloc = (destructor)generic_alias_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_methods = generic_alias_methods, +}; + +static PyObject * +generic_alias_new(PyObject *item) +{ + PyGenericAliasObject *o = PyObject_New(PyGenericAliasObject, &GenericAlias_Type); + if (o == NULL) { + return NULL; + } + Py_INCREF(item); + o->item = item; + return (PyObject*) o; +} + +typedef struct { + PyObject_HEAD +} PyGenericObject; + +static PyObject * +generic_class_getitem(PyObject *self, PyObject *args) +{ + PyObject *type, *item; + if (!PyArg_UnpackTuple(args, "__class_getitem__", 2, 2, &type, &item)) { + return NULL; + } + return generic_alias_new(item); +} + +static PyMethodDef generic_methods[] = { + {"__class_getitem__", generic_class_getitem, METH_VARARGS|METH_STATIC, NULL}, + {NULL} /* sentinel */ +}; + +PyTypeObject Generic_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Generic", + sizeof(PyGenericObject), + 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_methods = generic_methods, +}; + + static struct PyModuleDef _testcapimodule = { PyModuleDef_HEAD_INIT, "_testcapi", @@ -5094,6 +5169,16 @@ PyInit__testcapi(void) Py_INCREF(&awaitType); PyModule_AddObject(m, "awaitType", (PyObject *)&awaitType); + if (PyType_Ready(&GenericAlias_Type) < 0) + return NULL; + Py_INCREF(&GenericAlias_Type); + PyModule_AddObject(m, "GenericAlias", (PyObject *)&GenericAlias_Type); + + if (PyType_Ready(&Generic_Type) < 0) + return NULL; + Py_INCREF(&Generic_Type); + PyModule_AddObject(m, "Generic", (PyObject *)&Generic_Type); + PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception; if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) { return NULL; From webhook-mailer at python.org Sat Dec 16 14:08:08 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 16 Dec 2017 19:08:08 -0000 Subject: [Python-checkins] Fix PyObject_Hash signature in comment (#4905) Message-ID: https://github.com/python/cpython/commit/950840261c349e100ec5d7381fcd742c017e242d commit: 950840261c349e100ec5d7381fcd742c017e242d branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-16T21:08:05+02:00 summary: Fix PyObject_Hash signature in comment (#4905) files: M Include/abstract.h diff --git a/Include/abstract.h b/Include/abstract.h index 991c1c3ee00..3133cd10535 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -367,7 +367,7 @@ PyAPI_FUNC(PyObject *) _PyObject_CallMethodIdObjArgs( /* Implemented elsewhere: - long PyObject_Hash(PyObject *o); + Py_hash_t PyObject_Hash(PyObject *o); Compute and return the hash, hash_value, of an object, o. On failure, return -1. From webhook-mailer at python.org Sat Dec 16 14:58:41 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 16 Dec 2017 19:58:41 -0000 Subject: [Python-checkins] bpo-32250: Implement asyncio.current_task() and asyncio.all_tasks() (#4799) Message-ID: https://github.com/python/cpython/commit/44d1a5912ea629aa20fdc377a5ab69d9ccf75d61 commit: 44d1a5912ea629aa20fdc377a5ab69d9ccf75d61 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-16T21:58:38+02:00 summary: bpo-32250: Implement asyncio.current_task() and asyncio.all_tasks() (#4799) files: A Misc/NEWS.d/next/Library/2017-12-12-16-58-20.bpo-32250.UljTa0.rst M Doc/library/asyncio-task.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c M Modules/clinic/_asynciomodule.c.h diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 72fae5e8559..d85dddfa02e 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -528,6 +528,28 @@ Task functions the event loop object used by the underlying task or coroutine. If it's not provided, the default event loop is used. + +.. function:: current_task(loop=None): + + Return the current running :class:`Task` instance or ``None``, if + no task is running. + + If *loop* is ``None`` :func:`get_running_loop` is used to get + the current loop. + + .. versionadded:: 3.7 + + +.. function:: all_tasks(loop=None): + + Return a set of :class:`Task` objects created for the loop. + + If *loop* is ``None`` :func:`get_event_loop` is used for getting + current loop. + + .. versionadded:: 3.7 + + .. function:: as_completed(fs, \*, loop=None, timeout=None) Return an iterator whose values, when waited for, are :class:`Future` diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 172057e5a29..cdb483ae0eb 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -5,6 +5,8 @@ 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', 'wait', 'wait_for', 'as_completed', 'sleep', 'gather', 'shield', 'ensure_future', 'run_coroutine_threadsafe', + 'current_task', 'all_tasks', + '_register_task', '_unregister_task', '_enter_task', '_leave_task', ) import concurrent.futures @@ -21,6 +23,20 @@ from .coroutines import coroutine +def current_task(loop=None): + """Return a currently executed task.""" + if loop is None: + loop = events.get_running_loop() + return _current_tasks.get(loop) + + +def all_tasks(loop=None): + """Return a set of all tasks for the loop.""" + if loop is None: + loop = events.get_event_loop() + return {t for t, l in _all_tasks.items() if l is loop} + + class Task(futures.Future): """A coroutine wrapped in a Future.""" @@ -33,13 +49,6 @@ class Task(futures.Future): # _wakeup(). When _fut_waiter is not None, one of its callbacks # must be _wakeup(). - # Weak set containing all tasks alive. - _all_tasks = weakref.WeakSet() - - # Dictionary containing tasks that are currently active in - # all running event loops. {EventLoop: Task} - _current_tasks = {} - # If False, don't log a message if the task is destroyed whereas its # status is still pending _log_destroy_pending = True @@ -52,9 +61,13 @@ def current_task(cls, loop=None): None is returned when called not in the context of a Task. """ + warnings.warn("Task.current_task() is deprecated, " + "use asyncio.current_task() instead", + PendingDeprecationWarning, + stacklevel=2) if loop is None: loop = events.get_event_loop() - return cls._current_tasks.get(loop) + return current_task(loop) @classmethod def all_tasks(cls, loop=None): @@ -62,9 +75,11 @@ def all_tasks(cls, loop=None): By default all tasks for the current event loop are returned. """ - if loop is None: - loop = events.get_event_loop() - return {t for t in cls._all_tasks if t._loop is loop} + warnings.warn("Task.all_tasks() is deprecated, " + "use asyncio.all_tasks() instead", + PendingDeprecationWarning, + stacklevel=2) + return all_tasks(loop) def __init__(self, coro, *, loop=None): super().__init__(loop=loop) @@ -81,7 +96,7 @@ def __init__(self, coro, *, loop=None): self._coro = coro self._loop.call_soon(self._step) - self.__class__._all_tasks.add(self) + _register_task(self._loop, self) def __del__(self): if self._state == futures._PENDING and self._log_destroy_pending: @@ -173,7 +188,7 @@ def _step(self, exc=None): coro = self._coro self._fut_waiter = None - self.__class__._current_tasks[self._loop] = self + _enter_task(self._loop, self) # Call either coro.throw(exc) or coro.send(None). try: if exc is None: @@ -237,7 +252,7 @@ def _step(self, exc=None): new_exc = RuntimeError(f'Task got bad yield: {result!r}') self._loop.call_soon(self._step, new_exc) finally: - self.__class__._current_tasks.pop(self._loop) + _leave_task(self._loop, self) self = None # Needed to break cycles when an exception occurs. def _wakeup(self, future): @@ -715,3 +730,61 @@ def callback(): loop.call_soon_threadsafe(callback) return future + + +# WeakKeyDictionary of {Task: EventLoop} containing all tasks alive. +# Task should be a weak reference to remove entry on task garbage +# collection, EventLoop is required +# to not access to private task._loop attribute. +_all_tasks = weakref.WeakKeyDictionary() + +# Dictionary containing tasks that are currently active in +# all running event loops. {EventLoop: Task} +_current_tasks = {} + + +def _register_task(loop, task): + """Register a new task in asyncio as executed by loop. + + Returns None. + """ + _all_tasks[task] = loop + + +def _enter_task(loop, task): + current_task = _current_tasks.get(loop) + if current_task is not None: + raise RuntimeError(f"Cannot enter into task {task!r} while another " + f"task {current_task!r} is being executed.") + _current_tasks[loop] = task + + +def _leave_task(loop, task): + current_task = _current_tasks.get(loop) + if current_task is not task: + raise RuntimeError(f"Leaving task {task!r} does not match " + f"the current task {current_task!r}.") + del _current_tasks[loop] + + +def _unregister_task(loop, task): + _all_tasks.pop(task, None) + + +_py_register_task = _register_task +_py_unregister_task = _unregister_task +_py_enter_task = _enter_task +_py_leave_task = _leave_task + + +try: + from _asyncio import (_register_task, _unregister_task, + _enter_task, _leave_task, + _all_tasks, _current_tasks) +except ImportError: + pass +else: + _c_register_task = _register_task + _c_unregister_task = _unregister_task + _c_enter_task = _enter_task + _c_leave_task = _leave_task diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index a32dca13118..5429facbbcd 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1493,53 +1493,69 @@ def coro(): self.assertEqual(res, 'test') self.assertIsNone(t2.result()) - def test_current_task(self): + + def test_current_task_deprecated(self): Task = self.__class__.Task - self.assertIsNone(Task.current_task(loop=self.loop)) + with self.assertWarns(PendingDeprecationWarning): + self.assertIsNone(Task.current_task(loop=self.loop)) - @asyncio.coroutine - def coro(loop): - self.assertTrue(Task.current_task(loop=loop) is task) + async def coro(loop): + with self.assertWarns(PendingDeprecationWarning): + self.assertIs(Task.current_task(loop=loop), task) # See http://bugs.python.org/issue29271 for details: asyncio.set_event_loop(loop) try: - self.assertIs(Task.current_task(None), task) - self.assertIs(Task.current_task(), task) + with self.assertWarns(PendingDeprecationWarning): + self.assertIs(Task.current_task(None), task) + with self.assertWarns(PendingDeprecationWarning): + self.assertIs(Task.current_task(), task) finally: asyncio.set_event_loop(None) task = self.new_task(self.loop, coro(self.loop)) self.loop.run_until_complete(task) - self.assertIsNone(Task.current_task(loop=self.loop)) + with self.assertWarns(PendingDeprecationWarning): + self.assertIsNone(Task.current_task(loop=self.loop)) - def test_current_task_with_interleaving_tasks(self): - Task = self.__class__.Task + def test_current_task(self): + self.assertIsNone(asyncio.current_task(loop=self.loop)) - self.assertIsNone(Task.current_task(loop=self.loop)) + async def coro(loop): + self.assertIs(asyncio.current_task(loop=loop), task) + + self.assertIs(asyncio.current_task(None), task) + self.assertIs(asyncio.current_task(), task) + + task = self.new_task(self.loop, coro(self.loop)) + self.loop.run_until_complete(task) + self.assertIsNone(asyncio.current_task(loop=self.loop)) + + def test_current_task_with_interleaving_tasks(self): + self.assertIsNone(asyncio.current_task(loop=self.loop)) fut1 = self.new_future(self.loop) fut2 = self.new_future(self.loop) async def coro1(loop): - self.assertTrue(Task.current_task(loop=loop) is task1) + self.assertTrue(asyncio.current_task(loop=loop) is task1) await fut1 - self.assertTrue(Task.current_task(loop=loop) is task1) + self.assertTrue(asyncio.current_task(loop=loop) is task1) fut2.set_result(True) async def coro2(loop): - self.assertTrue(Task.current_task(loop=loop) is task2) + self.assertTrue(asyncio.current_task(loop=loop) is task2) fut1.set_result(True) await fut2 - self.assertTrue(Task.current_task(loop=loop) is task2) + self.assertTrue(asyncio.current_task(loop=loop) is task2) task1 = self.new_task(self.loop, coro1(self.loop)) task2 = self.new_task(self.loop, coro2(self.loop)) self.loop.run_until_complete(asyncio.wait((task1, task2), loop=self.loop)) - self.assertIsNone(Task.current_task(loop=self.loop)) + self.assertIsNone(asyncio.current_task(loop=self.loop)) # Some thorough tests for cancellation propagation through # coroutines, tasks and wait(). @@ -1826,6 +1842,16 @@ def foo(): self.assertIsInstance(exception, Exception) self.assertEqual(exception.args, ("foo", )) + def test_all_tasks_deprecated(self): + Task = self.__class__.Task + + async def coro(): + with self.assertWarns(PendingDeprecationWarning): + assert Task.all_tasks(self.loop) == {t} + + t = self.new_task(self.loop, coro()) + self.loop.run_until_complete(t) + def test_log_destroyed_pending_task(self): Task = self.__class__.Task @@ -1845,13 +1871,13 @@ def kill_me(loop): coro = kill_me(self.loop) task = asyncio.ensure_future(coro, loop=self.loop) - self.assertEqual(Task.all_tasks(loop=self.loop), {task}) + self.assertEqual(asyncio.all_tasks(loop=self.loop), {task}) # See http://bugs.python.org/issue29271 for details: asyncio.set_event_loop(self.loop) try: - self.assertEqual(Task.all_tasks(), {task}) - self.assertEqual(Task.all_tasks(None), {task}) + self.assertEqual(asyncio.all_tasks(), {task}) + self.assertEqual(asyncio.all_tasks(None), {task}) finally: asyncio.set_event_loop(None) @@ -1868,7 +1894,7 @@ def kill_me(loop): # no more reference to kill_me() task: the task is destroyed by the GC support.gc_collect() - self.assertEqual(Task.all_tasks(loop=self.loop), set()) + self.assertEqual(asyncio.all_tasks(loop=self.loop), set()) mock_handler.assert_called_with(self.loop, { 'message': 'Task was destroyed but it is pending!', @@ -2052,7 +2078,7 @@ def coro(): message = m_log.error.call_args[0][0] self.assertIn('Task was destroyed but it is pending', message) - self.assertEqual(self.Task.all_tasks(self.loop), set()) + self.assertEqual(asyncio.all_tasks(self.loop), set()) def test_create_task_with_noncoroutine(self): with self.assertRaisesRegex(TypeError, @@ -2201,6 +2227,140 @@ class PyTask_PyFuture_SubclassTests(BaseTaskTests, test_utils.TestCase): Future = futures._PyFuture +class BaseTaskIntrospectionTests: + _register_task = None + _unregister_task = None + _enter_task = None + _leave_task = None + + def test__register_task(self): + task = mock.Mock() + loop = mock.Mock() + self.assertEqual(asyncio.all_tasks(loop), set()) + self._register_task(loop, task) + self.assertEqual(asyncio.all_tasks(loop), {task}) + self._unregister_task(loop, task) + + def test__enter_task(self): + task = mock.Mock() + loop = mock.Mock() + self.assertIsNone(asyncio.current_task(loop)) + self._enter_task(loop, task) + self.assertIs(asyncio.current_task(loop), task) + self._leave_task(loop, task) + + def test__enter_task_failure(self): + task1 = mock.Mock() + task2 = mock.Mock() + loop = mock.Mock() + self._enter_task(loop, task1) + with self.assertRaises(RuntimeError): + self._enter_task(loop, task2) + self.assertIs(asyncio.current_task(loop), task1) + self._leave_task(loop, task1) + + def test__leave_task(self): + task = mock.Mock() + loop = mock.Mock() + self._enter_task(loop, task) + self._leave_task(loop, task) + self.assertIsNone(asyncio.current_task(loop)) + + def test__leave_task_failure1(self): + task1 = mock.Mock() + task2 = mock.Mock() + loop = mock.Mock() + self._enter_task(loop, task1) + with self.assertRaises(RuntimeError): + self._leave_task(loop, task2) + self.assertIs(asyncio.current_task(loop), task1) + self._leave_task(loop, task1) + + def test__leave_task_failure2(self): + task = mock.Mock() + loop = mock.Mock() + with self.assertRaises(RuntimeError): + self._leave_task(loop, task) + self.assertIsNone(asyncio.current_task(loop)) + + def test__unregister_task(self): + task = mock.Mock() + loop = mock.Mock() + self._register_task(loop, task) + self._unregister_task(loop, task) + self.assertEqual(asyncio.all_tasks(loop), set()) + + def test__unregister_task_not_registered(self): + task = mock.Mock() + loop = mock.Mock() + self._unregister_task(loop, task) + self.assertEqual(asyncio.all_tasks(loop), set()) + + +class PyIntrospectionTests(unittest.TestCase, BaseTaskIntrospectionTests): + _register_task = staticmethod(tasks._py_register_task) + _unregister_task = staticmethod(tasks._py_unregister_task) + _enter_task = staticmethod(tasks._py_enter_task) + _leave_task = staticmethod(tasks._py_leave_task) + + + at unittest.skipUnless(hasattr(tasks, '_c_register_task'), + 'requires the C _asyncio module') +class CIntrospectionTests(unittest.TestCase, BaseTaskIntrospectionTests): + _register_task = staticmethod(tasks._c_register_task) + _unregister_task = staticmethod(tasks._c_unregister_task) + _enter_task = staticmethod(tasks._c_enter_task) + _leave_task = staticmethod(tasks._c_leave_task) + + +class BaseCurrentLoopTests: + + def setUp(self): + super().setUp() + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + def tearDown(self): + self.loop.close() + asyncio.set_event_loop(None) + super().tearDown() + + def new_task(self, coro): + raise NotImplementedError + + def test_current_task_no_running_loop(self): + self.assertIsNone(asyncio.current_task(loop=self.loop)) + + def test_current_task_no_running_loop_implicit(self): + with self.assertRaises(RuntimeError): + asyncio.current_task() + + def test_current_task_with_implicit_loop(self): + async def coro(): + self.assertIs(asyncio.current_task(loop=self.loop), task) + + self.assertIs(asyncio.current_task(None), task) + self.assertIs(asyncio.current_task(), task) + + task = self.new_task(coro()) + self.loop.run_until_complete(task) + self.assertIsNone(asyncio.current_task(loop=self.loop)) + + +class PyCurrentLoopTests(BaseCurrentLoopTests, unittest.TestCase): + + def new_task(self, coro): + return tasks._PyTask(coro, loop=self.loop) + + + at unittest.skipUnless(hasattr(tasks, '_CTask'), + 'requires the C _asyncio module') +class CCurrentLoopTests(BaseCurrentLoopTests, unittest.TestCase): + + def new_task(self, coro): + return getattr(tasks, '_CTask')(coro, loop=self.loop) + + class GenericTaskTests(test_utils.TestCase): def test_future_subclass(self): @@ -2522,7 +2682,7 @@ def add(self, a, b, fail=False, cancel=False): if fail: raise RuntimeError("Fail!") if cancel: - asyncio.tasks.Task.current_task(self.loop).cancel() + asyncio.current_task(self.loop).cancel() yield return a + b @@ -2568,7 +2728,7 @@ def test_run_coroutine_threadsafe_with_timeout(self): self.loop.run_until_complete(future) test_utils.run_briefly(self.loop) # Check that there's no pending task (add has been cancelled) - for task in asyncio.Task.all_tasks(self.loop): + for task in asyncio.all_tasks(self.loop): self.assertTrue(task.done()) def test_run_coroutine_threadsafe_task_cancelled(self): diff --git a/Misc/NEWS.d/next/Library/2017-12-12-16-58-20.bpo-32250.UljTa0.rst b/Misc/NEWS.d/next/Library/2017-12-12-16-58-20.bpo-32250.UljTa0.rst new file mode 100644 index 00000000000..f2d016df39a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-12-16-58-20.bpo-32250.UljTa0.rst @@ -0,0 +1,5 @@ +Implement ``asyncio.current_task()`` and ``asyncio.all_tasks()``. Add +helpers intended to be used by alternative task implementations: +``asyncio._register_task``, ``asyncio._enter_task``, ``asyncio._leave_task`` +and ``asyncio._unregister_task``. Deprecate ``asyncio.Task.current_task()`` +and ``asyncio.Task.all_tasks()``. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 9ac1c44d48d..378bd08b0c5 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -11,9 +11,12 @@ module _asyncio /* identifiers used from some functions */ _Py_IDENTIFIER(__asyncio_running_event_loop__); _Py_IDENTIFIER(add_done_callback); +_Py_IDENTIFIER(all_tasks); _Py_IDENTIFIER(call_soon); _Py_IDENTIFIER(cancel); +_Py_IDENTIFIER(current_task); _Py_IDENTIFIER(get_event_loop); +_Py_IDENTIFIER(pop); _Py_IDENTIFIER(send); _Py_IDENTIFIER(throw); _Py_IDENTIFIER(_step); @@ -22,19 +25,29 @@ _Py_IDENTIFIER(_wakeup); /* State of the _asyncio module */ -static PyObject *all_tasks; -static PyObject *current_tasks; +static PyObject *asyncio_mod; +static PyObject *inspect_isgenerator; +static PyObject *os_getpid; static PyObject *traceback_extract_stack; static PyObject *asyncio_get_event_loop_policy; -static PyObject *asyncio_iscoroutine_func; static PyObject *asyncio_future_repr_info_func; -static PyObject *asyncio_task_repr_info_func; +static PyObject *asyncio_iscoroutine_func; static PyObject *asyncio_task_get_stack_func; static PyObject *asyncio_task_print_stack_func; +static PyObject *asyncio_task_repr_info_func; static PyObject *asyncio_InvalidStateError; static PyObject *asyncio_CancelledError; -static PyObject *inspect_isgenerator; -static PyObject *os_getpid; + + +/* WeakKeyDictionary of {Task: EventLoop} containing all tasks alive. + Task should be a weak reference to remove entry on task garbage + collection, EventLoop is required + to not access to private task._loop attribute. */ +static PyObject *current_tasks; + +/* Dictionary containing tasks that are currently active in + all running event loops. {EventLoop: Task} */ +static PyObject *all_tasks; typedef enum { @@ -1445,6 +1458,80 @@ TaskWakeupMethWrapper_new(TaskObj *task) return (PyObject*) o; } +/* ----- Task introspection helpers */ + +static int +register_task(PyObject *loop, PyObject *task) +{ + return PyObject_SetItem(all_tasks, task, loop); +} + + +static int +unregister_task(PyObject *loop, PyObject *task) +{ + PyObject *res; + + res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_pop, + task, Py_None, NULL); + if (res == NULL) { + return -1; + } + Py_DECREF(res); + return 0; +} + + +static int +enter_task(PyObject *loop, PyObject *task) +{ + PyObject *item; + Py_hash_t hash; + hash = PyObject_Hash(loop); + if (hash == -1) { + return -1; + } + item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash); + if (item != NULL) { + PyErr_Format( + PyExc_RuntimeError, + "Cannot enter into task %R while another " \ + "task %R is being executed.", + task, item, NULL); + return -1; + } + if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) { + return -1; + } + return 0; +} + + +static int +leave_task(PyObject *loop, PyObject *task) +/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/ +{ + PyObject *item; + Py_hash_t hash; + hash = PyObject_Hash(loop); + if (hash == -1) { + return -1; + } + item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash); + if (item != task) { + if (item == NULL) { + /* Not entered, replace with None */ + item = Py_None; + } + PyErr_Format( + PyExc_RuntimeError, + "Leaving task %R does not match the current task %R.", + task, item, NULL); + return -1; + } + return _PyDict_DelItem_KnownHash(current_tasks, loop, hash); +} + /* ----- Task */ /*[clinic input] @@ -1463,8 +1550,6 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) { PyObject *res; int tmp; - _Py_IDENTIFIER(add); - if (future_init((FutureObj*)self, loop)) { return -1; } @@ -1500,14 +1585,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) if (task_call_step_soon(self, NULL)) { return -1; } - - res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL); - if (res == NULL) { - return -1; - } - Py_DECREF(res); - - return 0; + return register_task(self->task_loop, (PyObject*)self); } static int @@ -1600,76 +1678,36 @@ static PyObject * _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop) /*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/ { - PyObject *res; + PyObject *ret; + PyObject *current_task_func; + + if (PyErr_WarnEx(PyExc_PendingDeprecationWarning, + "Task.current_task() is deprecated, " \ + "use asyncio.current_task() instead", + 1) < 0) { + return NULL; + } + + current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task); + if (current_task_func == NULL) { + return NULL; + } if (loop == Py_None) { loop = get_event_loop(); if (loop == NULL) { return NULL; } - - res = PyDict_GetItem(current_tasks, loop); + ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL); + Py_DECREF(current_task_func); Py_DECREF(loop); + return ret; } else { - res = PyDict_GetItem(current_tasks, loop); - } - - if (res == NULL) { - Py_RETURN_NONE; - } - else { - Py_INCREF(res); - return res; - } -} - -static PyObject * -task_all_tasks(PyObject *loop) -{ - PyObject *task; - PyObject *task_loop; - PyObject *set; - PyObject *iter; - - assert(loop != NULL); - - set = PySet_New(NULL); - if (set == NULL) { - return NULL; - } - - iter = PyObject_GetIter(all_tasks); - if (iter == NULL) { - goto fail; - } - - while ((task = PyIter_Next(iter))) { - task_loop = PyObject_GetAttrString(task, "_loop"); - if (task_loop == NULL) { - Py_DECREF(task); - goto fail; - } - if (task_loop == loop) { - if (PySet_Add(set, task) == -1) { - Py_DECREF(task_loop); - Py_DECREF(task); - goto fail; - } - } - Py_DECREF(task_loop); - Py_DECREF(task); - } - if (PyErr_Occurred()) { - goto fail; + ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL); + Py_DECREF(current_task_func); + return ret; } - Py_DECREF(iter); - return set; - -fail: - Py_DECREF(set); - Py_XDECREF(iter); - return NULL; } /*[clinic input] @@ -1688,20 +1726,22 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) /*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/ { PyObject *res; + PyObject *all_tasks_func; - if (loop == Py_None) { - loop = get_event_loop(); - if (loop == NULL) { - return NULL; - } - - res = task_all_tasks(loop); - Py_DECREF(loop); + all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks); + if (all_tasks_func == NULL) { + return NULL; } - else { - res = task_all_tasks(loop); + + if (PyErr_WarnEx(PyExc_PendingDeprecationWarning, + "Task.all_tasks() is deprecated, " \ + "use asyncio.all_tasks() instead", + 1) < 0) { + return NULL; } + res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL); + Py_DECREF(all_tasks_func); return res; } @@ -2437,11 +2477,8 @@ static PyObject * task_step(TaskObj *task, PyObject *exc) { PyObject *res; - PyObject *ot; - if (PyDict_SetItem(current_tasks, - task->task_loop, (PyObject*)task) == -1) - { + if (enter_task(task->task_loop, (PyObject*)task) < 0) { return NULL; } @@ -2450,19 +2487,16 @@ task_step(TaskObj *task, PyObject *exc) if (res == NULL) { PyObject *et, *ev, *tb; PyErr_Fetch(&et, &ev, &tb); - ot = _PyDict_Pop(current_tasks, task->task_loop, NULL); - Py_XDECREF(ot); + leave_task(task->task_loop, (PyObject*)task); _PyErr_ChainExceptions(et, ev, tb); return NULL; } else { - ot = _PyDict_Pop(current_tasks, task->task_loop, NULL); - if (ot == NULL) { + if(leave_task(task->task_loop, (PyObject*)task) < 0) { Py_DECREF(res); return NULL; } else { - Py_DECREF(ot); return res; } } @@ -2615,6 +2649,99 @@ _asyncio_get_running_loop_impl(PyObject *module) return loop; } +/*[clinic input] +_asyncio._register_task + + loop: object + task: object + +Register a new task in asyncio as executed by loop. + +Returns None. +[clinic start generated code]*/ + +static PyObject * +_asyncio__register_task_impl(PyObject *module, PyObject *loop, + PyObject *task) +/*[clinic end generated code: output=54c5cb733dbe0f38 input=9b5fee38fcb2c288]*/ +{ + if (register_task(loop, task) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + + +/*[clinic input] +_asyncio._unregister_task + + loop: object + task: object + +Unregister a task. + +Returns None. +[clinic start generated code]*/ + +static PyObject * +_asyncio__unregister_task_impl(PyObject *module, PyObject *loop, + PyObject *task) +/*[clinic end generated code: output=f634743a76b84ebc input=51fa1820634ef331]*/ +{ + if (unregister_task(loop, task) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + + +/*[clinic input] +_asyncio._enter_task + + loop: object + task: object + +Enter into task execution or resume suspended task. + +Task belongs to loop. + +Returns None. +[clinic start generated code]*/ + +static PyObject * +_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task) +/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/ +{ + if (enter_task(loop, task) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + + +/*[clinic input] +_asyncio._leave_task + + loop: object + task: object + +Leave task execution or suspend a task. + +Task belongs to loop. + +Returns None. +[clinic start generated code]*/ + +static PyObject * +_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task) +/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/ +{ + if (leave_task(loop, task) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + /*********************** Module **************************/ @@ -2622,26 +2749,37 @@ _asyncio_get_running_loop_impl(PyObject *module) static void module_free(void *m) { - Py_CLEAR(current_tasks); - Py_CLEAR(all_tasks); + Py_CLEAR(asyncio_mod); + Py_CLEAR(inspect_isgenerator); + Py_CLEAR(os_getpid); Py_CLEAR(traceback_extract_stack); - Py_CLEAR(asyncio_get_event_loop_policy); Py_CLEAR(asyncio_future_repr_info_func); + Py_CLEAR(asyncio_get_event_loop_policy); Py_CLEAR(asyncio_iscoroutine_func); - Py_CLEAR(asyncio_task_repr_info_func); Py_CLEAR(asyncio_task_get_stack_func); Py_CLEAR(asyncio_task_print_stack_func); + Py_CLEAR(asyncio_task_repr_info_func); Py_CLEAR(asyncio_InvalidStateError); Py_CLEAR(asyncio_CancelledError); - Py_CLEAR(inspect_isgenerator); - Py_CLEAR(os_getpid); + + Py_CLEAR(current_tasks); + Py_CLEAR(all_tasks); } static int module_init(void) { PyObject *module = NULL; - PyObject *cls; + + asyncio_mod = PyImport_ImportModule("asyncio"); + if (asyncio_mod == NULL) { + goto fail; + } + + current_tasks = PyDict_New(); + if (current_tasks == NULL) { + goto fail; + } #define WITH_MOD(NAME) \ Py_CLEAR(module); \ @@ -2681,19 +2819,15 @@ module_init(void) WITH_MOD("traceback") GET_MOD_ATTR(traceback_extract_stack, "extract_stack") + PyObject *weak_key_dict; WITH_MOD("weakref") - GET_MOD_ATTR(cls, "WeakSet") - all_tasks = _PyObject_CallNoArg(cls); - Py_DECREF(cls); + GET_MOD_ATTR(weak_key_dict, "WeakKeyDictionary"); + all_tasks = _PyObject_CallNoArg(weak_key_dict); + Py_CLEAR(weak_key_dict); if (all_tasks == NULL) { goto fail; } - current_tasks = PyDict_New(); - if (current_tasks == NULL) { - goto fail; - } - Py_DECREF(module); return 0; @@ -2713,6 +2847,10 @@ static PyMethodDef asyncio_methods[] = { _ASYNCIO_GET_RUNNING_LOOP_METHODDEF _ASYNCIO__GET_RUNNING_LOOP_METHODDEF _ASYNCIO__SET_RUNNING_LOOP_METHODDEF + _ASYNCIO__REGISTER_TASK_METHODDEF + _ASYNCIO__UNREGISTER_TASK_METHODDEF + _ASYNCIO__ENTER_TASK_METHODDEF + _ASYNCIO__LEAVE_TASK_METHODDEF {NULL, NULL} }; @@ -2768,5 +2906,17 @@ PyInit__asyncio(void) return NULL; } + Py_INCREF(all_tasks); + if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) { + Py_DECREF(all_tasks); + return NULL; + } + + Py_INCREF(current_tasks); + if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) { + Py_DECREF(current_tasks); + return NULL; + } + return m; } diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h index 952316cc195..9d5dea52c8e 100644 --- a/Modules/clinic/_asynciomodule.c.h +++ b/Modules/clinic/_asynciomodule.c.h @@ -595,4 +595,142 @@ _asyncio_get_running_loop(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _asyncio_get_running_loop_impl(module); } -/*[clinic end generated code: output=21e5424c3a5572b0 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_asyncio__register_task__doc__, +"_register_task($module, /, loop, task)\n" +"--\n" +"\n" +"Register a new task in asyncio as executed by loop.\n" +"\n" +"Returns None."); + +#define _ASYNCIO__REGISTER_TASK_METHODDEF \ + {"_register_task", (PyCFunction)_asyncio__register_task, METH_FASTCALL|METH_KEYWORDS, _asyncio__register_task__doc__}, + +static PyObject * +_asyncio__register_task_impl(PyObject *module, PyObject *loop, + PyObject *task); + +static PyObject * +_asyncio__register_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"loop", "task", NULL}; + static _PyArg_Parser _parser = {"OO:_register_task", _keywords, 0}; + PyObject *loop; + PyObject *task; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &loop, &task)) { + goto exit; + } + return_value = _asyncio__register_task_impl(module, loop, task); + +exit: + return return_value; +} + +PyDoc_STRVAR(_asyncio__unregister_task__doc__, +"_unregister_task($module, /, loop, task)\n" +"--\n" +"\n" +"Unregister a task.\n" +"\n" +"Returns None."); + +#define _ASYNCIO__UNREGISTER_TASK_METHODDEF \ + {"_unregister_task", (PyCFunction)_asyncio__unregister_task, METH_FASTCALL|METH_KEYWORDS, _asyncio__unregister_task__doc__}, + +static PyObject * +_asyncio__unregister_task_impl(PyObject *module, PyObject *loop, + PyObject *task); + +static PyObject * +_asyncio__unregister_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"loop", "task", NULL}; + static _PyArg_Parser _parser = {"OO:_unregister_task", _keywords, 0}; + PyObject *loop; + PyObject *task; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &loop, &task)) { + goto exit; + } + return_value = _asyncio__unregister_task_impl(module, loop, task); + +exit: + return return_value; +} + +PyDoc_STRVAR(_asyncio__enter_task__doc__, +"_enter_task($module, /, loop, task)\n" +"--\n" +"\n" +"Enter into task execution or resume suspended task.\n" +"\n" +"Task belongs to loop.\n" +"\n" +"Returns None."); + +#define _ASYNCIO__ENTER_TASK_METHODDEF \ + {"_enter_task", (PyCFunction)_asyncio__enter_task, METH_FASTCALL|METH_KEYWORDS, _asyncio__enter_task__doc__}, + +static PyObject * +_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task); + +static PyObject * +_asyncio__enter_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"loop", "task", NULL}; + static _PyArg_Parser _parser = {"OO:_enter_task", _keywords, 0}; + PyObject *loop; + PyObject *task; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &loop, &task)) { + goto exit; + } + return_value = _asyncio__enter_task_impl(module, loop, task); + +exit: + return return_value; +} + +PyDoc_STRVAR(_asyncio__leave_task__doc__, +"_leave_task($module, /, loop, task)\n" +"--\n" +"\n" +"Leave task execution or suspend a task.\n" +"\n" +"Task belongs to loop.\n" +"\n" +"Returns None."); + +#define _ASYNCIO__LEAVE_TASK_METHODDEF \ + {"_leave_task", (PyCFunction)_asyncio__leave_task, METH_FASTCALL|METH_KEYWORDS, _asyncio__leave_task__doc__}, + +static PyObject * +_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task); + +static PyObject * +_asyncio__leave_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"loop", "task", NULL}; + static _PyArg_Parser _parser = {"OO:_leave_task", _keywords, 0}; + PyObject *loop; + PyObject *task; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &loop, &task)) { + goto exit; + } + return_value = _asyncio__leave_task_impl(module, loop, task); + +exit: + return return_value; +} +/*[clinic end generated code: output=0033af17965b51b4 input=a9049054013a1b77]*/ From solipsis at pitrou.net Sun Dec 17 04:06:43 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 17 Dec 2017 09:06:43 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-2 Message-ID: <20171217090643.122954.3B7782C9D53CB927@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 0] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [1, -2, 2] memory blocks, sum=1 test_multiprocessing_forkserver leaked [1, 0, -2] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog05jiG2', '--timeout', '7200'] From webhook-mailer at python.org Sun Dec 17 09:41:34 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sun, 17 Dec 2017 14:41:34 -0000 Subject: [Python-checkins] bpo-32351: Use fastpath in asyncio.sleep if delay<0 (#4908) Message-ID: https://github.com/python/cpython/commit/5382c05021026fe623def829d121f5f6af4909fb commit: 5382c05021026fe623def829d121f5f6af4909fb branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-17T16:41:30+02:00 summary: bpo-32351: Use fastpath in asyncio.sleep if delay<0 (#4908) * Use fastpath in asyncio.sleep if delay<0 * Add NEWS entry files: A Misc/NEWS.d/next/Library/2017-12-17-14-23-23.bpo-32351.95fh2K.rst M Lib/asyncio/tasks.py diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index cdb483ae0eb..275141c65e7 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -503,7 +503,7 @@ def __sleep0(): async def sleep(delay, result=None, *, loop=None): """Coroutine that completes after a given time (in seconds).""" - if delay == 0: + if delay <= 0: await __sleep0() return result diff --git a/Misc/NEWS.d/next/Library/2017-12-17-14-23-23.bpo-32351.95fh2K.rst b/Misc/NEWS.d/next/Library/2017-12-17-14-23-23.bpo-32351.95fh2K.rst new file mode 100644 index 00000000000..56f52d2a418 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-17-14-23-23.bpo-32351.95fh2K.rst @@ -0,0 +1 @@ +Use fastpath in asyncio.sleep if delay<0 (2x boost) From webhook-mailer at python.org Sun Dec 17 13:34:02 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sun, 17 Dec 2017 18:34:02 -0000 Subject: [Python-checkins] add 'extern' to pygetopt.h symbols, so then don't end up in comdat (#4909) Message-ID: https://github.com/python/cpython/commit/4c72bc4a38eced10a55ba7071e084b26a2b5ed4b commit: 4c72bc4a38eced10a55ba7071e084b26a2b5ed4b branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-17T10:34:00-08:00 summary: add 'extern' to pygetopt.h symbols, so then don't end up in comdat (#4909) bpo-32264 files: M Include/internal/pygetopt.h diff --git a/Include/internal/pygetopt.h b/Include/internal/pygetopt.h index df6f18354ee..8ef2ada72fe 100644 --- a/Include/internal/pygetopt.h +++ b/Include/internal/pygetopt.h @@ -1,11 +1,11 @@ #ifndef Py_INTERNAL_PYGETOPT_H #define Py_INTERNAL_PYGETOPT_H -int _PyOS_opterr; -int _PyOS_optind; -wchar_t *_PyOS_optarg; +extern int _PyOS_opterr; +extern int _PyOS_optind; +extern wchar_t *_PyOS_optarg; -void _PyOS_ResetGetOpt(void); +extern void _PyOS_ResetGetOpt(void); typedef struct { const wchar_t *name; @@ -13,7 +13,7 @@ typedef struct { int val; } _PyOS_LongOption; -int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring, - const _PyOS_LongOption *longopts, int *longindex); +extern int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring, + const _PyOS_LongOption *longopts, int *longindex); #endif /* !Py_INTERNAL_PYGETOPT_H */ From webhook-mailer at python.org Sun Dec 17 20:19:50 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 18 Dec 2017 01:19:50 -0000 Subject: [Python-checkins] bpo-32348: Optimize asyncio.Future schedule/add/remove callback. (#4907) Message-ID: https://github.com/python/cpython/commit/1b7c11ff0ee3efafbf5b38c3c6f37de5d63efb81 commit: 1b7c11ff0ee3efafbf5b38c3c6f37de5d63efb81 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-17T20:19:47-05:00 summary: bpo-32348: Optimize asyncio.Future schedule/add/remove callback. (#4907) files: A Misc/NEWS.d/next/Library/2017-12-16-18-50-57.bpo-32348.5j__he.rst M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 444d1df02be..5652a42690e 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -145,37 +145,60 @@ def test_constructor_positional(self): self.assertRaises(TypeError, self._new_future, 42) def test_uninitialized(self): + # Test that C Future doesn't crash when Future.__init__() + # call was skipped. + fut = self.cls.__new__(self.cls, loop=self.loop) self.assertRaises(asyncio.InvalidStateError, fut.result) + fut = self.cls.__new__(self.cls, loop=self.loop) self.assertRaises(asyncio.InvalidStateError, fut.exception) + fut = self.cls.__new__(self.cls, loop=self.loop) with self.assertRaises((RuntimeError, AttributeError)): fut.set_result(None) + fut = self.cls.__new__(self.cls, loop=self.loop) with self.assertRaises((RuntimeError, AttributeError)): fut.set_exception(Exception) + fut = self.cls.__new__(self.cls, loop=self.loop) with self.assertRaises((RuntimeError, AttributeError)): fut.cancel() + fut = self.cls.__new__(self.cls, loop=self.loop) with self.assertRaises((RuntimeError, AttributeError)): fut.add_done_callback(lambda f: None) + fut = self.cls.__new__(self.cls, loop=self.loop) with self.assertRaises((RuntimeError, AttributeError)): fut.remove_done_callback(lambda f: None) + fut = self.cls.__new__(self.cls, loop=self.loop) with self.assertRaises((RuntimeError, AttributeError)): fut._schedule_callbacks() + fut = self.cls.__new__(self.cls, loop=self.loop) try: repr(fut) - except AttributeError: + except (RuntimeError, AttributeError): + pass + + fut = self.cls.__new__(self.cls, loop=self.loop) + try: + fut.__await__() + except RuntimeError: + pass + + fut = self.cls.__new__(self.cls, loop=self.loop) + try: + iter(fut) + except RuntimeError: pass + fut = self.cls.__new__(self.cls, loop=self.loop) - fut.cancelled() - fut.done() - iter(fut) + self.assertFalse(fut.cancelled()) + self.assertFalse(fut.done()) def test_cancel(self): f = self._new_future(loop=self.loop) @@ -246,30 +269,32 @@ def test_future_repr(self): self.loop.set_debug(True) f_pending_debug = self._new_future(loop=self.loop) frame = f_pending_debug._source_traceback[-1] - self.assertEqual(repr(f_pending_debug), - '' - % (frame[0], frame[1])) + self.assertEqual( + repr(f_pending_debug), + f'<{self.cls.__name__} pending created at {frame[0]}:{frame[1]}>') f_pending_debug.cancel() self.loop.set_debug(False) f_pending = self._new_future(loop=self.loop) - self.assertEqual(repr(f_pending), '') + self.assertEqual(repr(f_pending), f'<{self.cls.__name__} pending>') f_pending.cancel() f_cancelled = self._new_future(loop=self.loop) f_cancelled.cancel() - self.assertEqual(repr(f_cancelled), '') + self.assertEqual(repr(f_cancelled), f'<{self.cls.__name__} cancelled>') f_result = self._new_future(loop=self.loop) f_result.set_result(4) - self.assertEqual(repr(f_result), '') + self.assertEqual( + repr(f_result), f'<{self.cls.__name__} finished result=4>') self.assertEqual(f_result.result(), 4) exc = RuntimeError() f_exception = self._new_future(loop=self.loop) f_exception.set_exception(exc) - self.assertEqual(repr(f_exception), - '') + self.assertEqual( + repr(f_exception), + f'<{self.cls.__name__} finished exception=RuntimeError()>') self.assertIs(f_exception.exception(), exc) def func_repr(func): @@ -280,11 +305,12 @@ def func_repr(func): f_one_callbacks = self._new_future(loop=self.loop) f_one_callbacks.add_done_callback(_fakefunc) fake_repr = func_repr(_fakefunc) - self.assertRegex(repr(f_one_callbacks), - r'' % fake_repr) + self.assertRegex( + repr(f_one_callbacks), + r'<' + self.cls.__name__ + r' pending cb=\[%s\]>' % fake_repr) f_one_callbacks.cancel() self.assertEqual(repr(f_one_callbacks), - '') + f'<{self.cls.__name__} cancelled>') f_two_callbacks = self._new_future(loop=self.loop) f_two_callbacks.add_done_callback(first_cb) @@ -292,7 +318,7 @@ def func_repr(func): first_repr = func_repr(first_cb) last_repr = func_repr(last_cb) self.assertRegex(repr(f_two_callbacks), - r'' + r'<' + self.cls.__name__ + r' pending cb=\[%s, %s\]>' % (first_repr, last_repr)) f_many_callbacks = self._new_future(loop=self.loop) @@ -301,11 +327,12 @@ def func_repr(func): f_many_callbacks.add_done_callback(_fakefunc) f_many_callbacks.add_done_callback(last_cb) cb_regex = r'%s, <8 more>, %s' % (first_repr, last_repr) - self.assertRegex(repr(f_many_callbacks), - r'' % cb_regex) + self.assertRegex( + repr(f_many_callbacks), + r'<' + self.cls.__name__ + r' pending cb=\[%s\]>' % cb_regex) f_many_callbacks.cancel() self.assertEqual(repr(f_many_callbacks), - '') + f'<{self.cls.__name__} cancelled>') def test_copy_state(self): from asyncio.futures import _copy_future_state @@ -475,7 +502,7 @@ def memory_error(): support.gc_collect() if sys.version_info >= (3, 4): - regex = r'^Future exception was never retrieved\n' + regex = f'^{self.cls.__name__} exception was never retrieved\n' exc_info = (type(exc), exc, exc.__traceback__) m_log.error.assert_called_once_with(mock.ANY, exc_info=exc_info) else: @@ -531,7 +558,16 @@ def __del__(self): @unittest.skipUnless(hasattr(futures, '_CFuture'), 'requires the C _asyncio module') class CFutureTests(BaseFutureTests, test_utils.TestCase): - cls = getattr(futures, '_CFuture') + cls = futures._CFuture + + + at unittest.skipUnless(hasattr(futures, '_CFuture'), + 'requires the C _asyncio module') +class CSubFutureTests(BaseFutureTests, test_utils.TestCase): + class CSubFuture(futures._CFuture): + pass + + cls = CSubFuture class PyFutureTests(BaseFutureTests, test_utils.TestCase): @@ -556,6 +592,76 @@ def bag_appender(future): def _new_future(self): raise NotImplementedError + def test_callbacks_remove_first_callback(self): + bag = [] + f = self._new_future() + + cb1 = self._make_callback(bag, 42) + cb2 = self._make_callback(bag, 17) + cb3 = self._make_callback(bag, 100) + + f.add_done_callback(cb1) + f.add_done_callback(cb2) + f.add_done_callback(cb3) + + f.remove_done_callback(cb1) + f.remove_done_callback(cb1) + + self.assertEqual(bag, []) + f.set_result('foo') + + self.run_briefly() + + self.assertEqual(bag, [17, 100]) + self.assertEqual(f.result(), 'foo') + + def test_callbacks_remove_first_and_second_callback(self): + bag = [] + f = self._new_future() + + cb1 = self._make_callback(bag, 42) + cb2 = self._make_callback(bag, 17) + cb3 = self._make_callback(bag, 100) + + f.add_done_callback(cb1) + f.add_done_callback(cb2) + f.add_done_callback(cb3) + + f.remove_done_callback(cb1) + f.remove_done_callback(cb2) + f.remove_done_callback(cb1) + + self.assertEqual(bag, []) + f.set_result('foo') + + self.run_briefly() + + self.assertEqual(bag, [100]) + self.assertEqual(f.result(), 'foo') + + def test_callbacks_remove_third_callback(self): + bag = [] + f = self._new_future() + + cb1 = self._make_callback(bag, 42) + cb2 = self._make_callback(bag, 17) + cb3 = self._make_callback(bag, 100) + + f.add_done_callback(cb1) + f.add_done_callback(cb2) + f.add_done_callback(cb3) + + f.remove_done_callback(cb3) + f.remove_done_callback(cb3) + + self.assertEqual(bag, []) + f.set_result('foo') + + self.run_briefly() + + self.assertEqual(bag, [42, 17]) + self.assertEqual(f.result(), 'foo') + def test_callbacks_invoked_on_set_result(self): bag = [] f = self._new_future() @@ -678,6 +784,17 @@ def _new_future(self): return futures._CFuture(loop=self.loop) + at unittest.skipUnless(hasattr(futures, '_CFuture'), + 'requires the C _asyncio module') +class CSubFutureDoneCallbackTests(BaseFutureDoneCallbackTests, + test_utils.TestCase): + + def _new_future(self): + class CSubFuture(futures._CFuture): + pass + return CSubFuture(loop=self.loop) + + class PyFutureDoneCallbackTests(BaseFutureDoneCallbackTests, test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 5429facbbcd..47206613993 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2187,23 +2187,51 @@ def test_subclasses_ctask_cfuture(self): return cls - at unittest.skipUnless(hasattr(futures, '_CFuture'), + at unittest.skipUnless(hasattr(futures, '_CFuture') and + hasattr(tasks, '_CTask'), 'requires the C _asyncio module') class CTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase): Task = getattr(tasks, '_CTask', None) Future = getattr(futures, '_CFuture', None) - at unittest.skipUnless(hasattr(futures, '_CFuture'), + at unittest.skipUnless(hasattr(futures, '_CFuture') and + hasattr(tasks, '_CTask'), 'requires the C _asyncio module') @add_subclass_tests class CTask_CFuture_SubclassTests(BaseTaskTests, test_utils.TestCase): - Task = getattr(tasks, '_CTask', None) - Future = getattr(futures, '_CFuture', None) + + class Task(tasks._CTask): + pass + + class Future(futures._CFuture): + pass + + + at unittest.skipUnless(hasattr(tasks, '_CTask'), + 'requires the C _asyncio module') + at add_subclass_tests +class CTaskSubclass_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): + + class Task(tasks._CTask): + pass + + Future = futures._PyFuture @unittest.skipUnless(hasattr(futures, '_CFuture'), 'requires the C _asyncio module') + at add_subclass_tests +class PyTask_CFutureSubclass_Tests(BaseTaskTests, test_utils.TestCase): + + class Future(futures._CFuture): + pass + + Task = tasks._PyTask + + + at unittest.skipUnless(hasattr(tasks, '_CTask'), + 'requires the C _asyncio module') class CTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): Task = getattr(tasks, '_CTask', None) Future = futures._PyFuture @@ -2223,8 +2251,11 @@ class PyTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): @add_subclass_tests class PyTask_PyFuture_SubclassTests(BaseTaskTests, test_utils.TestCase): - Task = tasks._PyTask - Future = futures._PyFuture + class Task(tasks._PyTask): + pass + + class Future(futures._PyFuture): + pass class BaseTaskIntrospectionTests: diff --git a/Misc/NEWS.d/next/Library/2017-12-16-18-50-57.bpo-32348.5j__he.rst b/Misc/NEWS.d/next/Library/2017-12-16-18-50-57.bpo-32348.5j__he.rst new file mode 100644 index 00000000000..b3618db7c33 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-16-18-50-57.bpo-32348.5j__he.rst @@ -0,0 +1,2 @@ +Optimize asyncio.Future schedule/add/remove callback. The optimization +shows 3-6% performance improvements of async/await code. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 378bd08b0c5..5030a40b873 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -59,6 +59,7 @@ typedef enum { #define FutureObj_HEAD(prefix) \ PyObject_HEAD \ PyObject *prefix##_loop; \ + PyObject *prefix##_callback0; \ PyObject *prefix##_callbacks; \ PyObject *prefix##_exception; \ PyObject *prefix##_result; \ @@ -93,6 +94,16 @@ typedef struct { } TaskWakeupMethWrapper; +static PyTypeObject FutureType; +static PyTypeObject TaskType; + + +#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType) +#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType) + +#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType) +#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType) + #include "clinic/_asynciomodule.c.h" @@ -101,6 +112,7 @@ class _asyncio.Future "FutureObj *" "&Future_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/ + /* Get FutureIter from Future */ static PyObject* future_new_iter(PyObject *); static inline int future_call_schedule_callbacks(FutureObj *); @@ -233,47 +245,95 @@ get_event_loop(void) } +static int +call_soon(PyObject *loop, PyObject *func, PyObject *arg) +{ + PyObject *handle; + handle = _PyObject_CallMethodIdObjArgs( + loop, &PyId_call_soon, func, arg, NULL); + if (handle == NULL) { + return -1; + } + Py_DECREF(handle); + return 0; +} + + +static inline int +future_is_alive(FutureObj *fut) +{ + return fut->fut_loop != NULL; +} + + +static inline int +future_ensure_alive(FutureObj *fut) +{ + if (!future_is_alive(fut)) { + PyErr_SetString(PyExc_RuntimeError, + "Future object is not initialized."); + return -1; + } + return 0; +} + + +#define ENSURE_FUTURE_ALIVE(fut) \ + do { \ + assert(Future_Check(fut) || Task_Check(fut)); \ + if (future_ensure_alive((FutureObj*)fut)) { \ + return NULL; \ + } \ + } while(0); + + static int future_schedule_callbacks(FutureObj *fut) { Py_ssize_t len; - PyObject *callbacks; - int i; + Py_ssize_t i; + + if (fut->fut_callback0 != NULL) { + /* There's a 1st callback */ + + int ret = call_soon( + fut->fut_loop, fut->fut_callback0, (PyObject *)fut); + Py_CLEAR(fut->fut_callback0); + if (ret) { + /* If an error occurs in pure-Python implementation, + all callbacks are cleared. */ + Py_CLEAR(fut->fut_callbacks); + return ret; + } + + /* we called the first callback, now try calling + callbacks from the 'fut_callbacks' list. */ + } if (fut->fut_callbacks == NULL) { - PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object"); - return -1; + /* No more callbacks, return. */ + return 0; } len = PyList_GET_SIZE(fut->fut_callbacks); if (len == 0) { + /* The list of callbacks was empty; clear it and return. */ + Py_CLEAR(fut->fut_callbacks); return 0; } - callbacks = PyList_GetSlice(fut->fut_callbacks, 0, len); - if (callbacks == NULL) { - return -1; - } - if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) { - Py_DECREF(callbacks); - return -1; - } - for (i = 0; i < len; i++) { - PyObject *handle; - PyObject *cb = PyList_GET_ITEM(callbacks, i); + PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i); - handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, &PyId_call_soon, - cb, fut, NULL); - - if (handle == NULL) { - Py_DECREF(callbacks); + if (call_soon(fut->fut_loop, cb, (PyObject *)fut)) { + /* If an error occurs in pure-Python implementation, + all callbacks are cleared. */ + Py_CLEAR(fut->fut_callbacks); return -1; } - Py_DECREF(handle); } - Py_DECREF(callbacks); + Py_CLEAR(fut->fut_callbacks); return 0; } @@ -311,10 +371,8 @@ future_init(FutureObj *fut, PyObject *loop) } } - Py_XSETREF(fut->fut_callbacks, PyList_New(0)); - if (fut->fut_callbacks == NULL) { - return -1; - } + fut->fut_callback0 = NULL; + fut->fut_callbacks = NULL; return 0; } @@ -322,6 +380,10 @@ future_init(FutureObj *fut, PyObject *loop) static PyObject * future_set_result(FutureObj *fut, PyObject *res) { + if (future_ensure_alive(fut)) { + return NULL; + } + if (fut->fut_state != STATE_PENDING) { PyErr_SetString(asyncio_InvalidStateError, "invalid state"); return NULL; @@ -416,25 +478,61 @@ future_get_result(FutureObj *fut, PyObject **result) static PyObject * future_add_done_callback(FutureObj *fut, PyObject *arg) { + if (!future_is_alive(fut)) { + PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object"); + return NULL; + } + if (fut->fut_state != STATE_PENDING) { - PyObject *handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, - &PyId_call_soon, - arg, fut, NULL); - if (handle == NULL) { + /* The future is done/cancelled, so schedule the callback + right away. */ + if (call_soon(fut->fut_loop, arg, (PyObject*) fut)) { return NULL; } - Py_DECREF(handle); } else { - if (fut->fut_callbacks == NULL) { - PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object"); - return NULL; + /* The future is pending, add a callback. + + Callbacks in the future object are stored as follows: + + callback0 -- a pointer to the first callback + callbacks -- a list of 2nd, 3rd, ... callbacks + + Invariants: + + * callbacks != NULL: + There are some callbacks in in the list. Just + add the new callback to it. + + * callbacks == NULL and callback0 == NULL: + This is the first callback. Set it to callback0. + + * callbacks == NULL and callback0 != NULL: + This is a second callback. Initialize callbacks + with a new list and add the new callback to it. + */ + + if (fut->fut_callbacks != NULL) { + int err = PyList_Append(fut->fut_callbacks, arg); + if (err != 0) { + return NULL; + } } - int err = PyList_Append(fut->fut_callbacks, arg); - if (err != 0) { - return NULL; + else if (fut->fut_callback0 == NULL) { + Py_INCREF(arg); + fut->fut_callback0 = arg; + } + else { + fut->fut_callbacks = PyList_New(1); + if (fut->fut_callbacks == NULL) { + return NULL; + } + + Py_INCREF(arg); + PyList_SET_ITEM(fut->fut_callbacks, 0, arg); } } + Py_RETURN_NONE; } @@ -487,6 +585,7 @@ static int FutureObj_clear(FutureObj *fut) { Py_CLEAR(fut->fut_loop); + Py_CLEAR(fut->fut_callback0); Py_CLEAR(fut->fut_callbacks); Py_CLEAR(fut->fut_result); Py_CLEAR(fut->fut_exception); @@ -499,6 +598,7 @@ static int FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) { Py_VISIT(fut->fut_loop); + Py_VISIT(fut->fut_callback0); Py_VISIT(fut->fut_callbacks); Py_VISIT(fut->fut_result); Py_VISIT(fut->fut_exception); @@ -522,6 +622,13 @@ _asyncio_Future_result_impl(FutureObj *self) /*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/ { PyObject *result; + + if (!future_is_alive(self)) { + PyErr_SetString(asyncio_InvalidStateError, + "Future object is not initialized."); + return NULL; + } + int res = future_get_result(self, &result); if (res == -1) { @@ -554,6 +661,12 @@ static PyObject * _asyncio_Future_exception_impl(FutureObj *self) /*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/ { + if (!future_is_alive(self)) { + PyErr_SetString(asyncio_InvalidStateError, + "Future object is not initialized."); + return NULL; + } + if (self->fut_state == STATE_CANCELLED) { PyErr_SetNone(asyncio_CancelledError); return NULL; @@ -589,6 +702,7 @@ static PyObject * _asyncio_Future_set_result(FutureObj *self, PyObject *res) /*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/ { + ENSURE_FUTURE_ALIVE(self) return future_set_result(self, res); } @@ -608,6 +722,7 @@ static PyObject * _asyncio_Future_set_exception(FutureObj *self, PyObject *exception) /*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/ { + ENSURE_FUTURE_ALIVE(self) return future_set_exception(self, exception); } @@ -648,15 +763,45 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn) { PyObject *newlist; Py_ssize_t len, i, j=0; + Py_ssize_t cleared_callback0 = 0; + + ENSURE_FUTURE_ALIVE(self) + + if (self->fut_callback0 != NULL) { + int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ); + if (cmp == -1) { + return NULL; + } + if (cmp == 1) { + /* callback0 == fn */ + Py_CLEAR(self->fut_callback0); + cleared_callback0 = 1; + } + } if (self->fut_callbacks == NULL) { - PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object"); - return NULL; + return PyLong_FromSsize_t(cleared_callback0); } len = PyList_GET_SIZE(self->fut_callbacks); if (len == 0) { - return PyLong_FromSsize_t(0); + Py_CLEAR(self->fut_callbacks); + return PyLong_FromSsize_t(cleared_callback0); + } + + if (len == 1) { + int cmp = PyObject_RichCompareBool( + fn, PyList_GET_ITEM(self->fut_callbacks, 0), Py_EQ); + if (cmp == -1) { + return NULL; + } + if (cmp == 1) { + /* callbacks[0] == fn */ + Py_CLEAR(self->fut_callbacks); + return PyLong_FromSsize_t(1 + cleared_callback0); + } + /* callbacks[0] != fn and len(callbacks) == 1 */ + return PyLong_FromSsize_t(cleared_callback0); } newlist = PyList_New(len); @@ -683,6 +828,12 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn) } } + if (j == 0) { + Py_CLEAR(self->fut_callbacks); + Py_DECREF(newlist); + return PyLong_FromSsize_t(len + cleared_callback0); + } + if (j < len) { Py_SIZE(newlist) = j; } @@ -694,7 +845,7 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn) } } Py_DECREF(newlist); - return PyLong_FromSsize_t(len - j); + return PyLong_FromSsize_t(len - j + cleared_callback0); fail: Py_DECREF(newlist); @@ -715,6 +866,7 @@ static PyObject * _asyncio_Future_cancel_impl(FutureObj *self) /*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/ { + ENSURE_FUTURE_ALIVE(self) return future_cancel(self); } @@ -728,7 +880,7 @@ static PyObject * _asyncio_Future_cancelled_impl(FutureObj *self) /*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/ { - if (self->fut_state == STATE_CANCELLED) { + if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) { Py_RETURN_TRUE; } else { @@ -749,7 +901,7 @@ static PyObject * _asyncio_Future_done_impl(FutureObj *self) /*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/ { - if (self->fut_state == STATE_PENDING) { + if (!future_is_alive(self) || self->fut_state == STATE_PENDING) { Py_RETURN_FALSE; } else { @@ -760,7 +912,7 @@ _asyncio_Future_done_impl(FutureObj *self) static PyObject * FutureObj_get_blocking(FutureObj *fut) { - if (fut->fut_blocking) { + if (future_is_alive(fut) && fut->fut_blocking) { Py_RETURN_TRUE; } else { @@ -771,6 +923,10 @@ FutureObj_get_blocking(FutureObj *fut) static int FutureObj_set_blocking(FutureObj *fut, PyObject *val) { + if (future_ensure_alive(fut)) { + return -1; + } + int is_true = PyObject_IsTrue(val); if (is_true < 0) { return -1; @@ -782,6 +938,7 @@ FutureObj_set_blocking(FutureObj *fut, PyObject *val) static PyObject * FutureObj_get_log_traceback(FutureObj *fut) { + ENSURE_FUTURE_ALIVE(fut) if (fut->fut_log_tb) { Py_RETURN_TRUE; } @@ -804,7 +961,7 @@ FutureObj_set_log_traceback(FutureObj *fut, PyObject *val) static PyObject * FutureObj_get_loop(FutureObj *fut) { - if (fut->fut_loop == NULL) { + if (!future_is_alive(fut)) { Py_RETURN_NONE; } Py_INCREF(fut->fut_loop); @@ -814,16 +971,57 @@ FutureObj_get_loop(FutureObj *fut) static PyObject * FutureObj_get_callbacks(FutureObj *fut) { + Py_ssize_t i; + Py_ssize_t len; + PyObject *new_list; + + ENSURE_FUTURE_ALIVE(fut) + if (fut->fut_callbacks == NULL) { - Py_RETURN_NONE; + if (fut->fut_callback0 == NULL) { + Py_RETURN_NONE; + } + else { + new_list = PyList_New(1); + if (new_list == NULL) { + return NULL; + } + Py_INCREF(fut->fut_callback0); + PyList_SET_ITEM(new_list, 0, fut->fut_callback0); + return new_list; + } + } + + assert(fut->fut_callbacks != NULL); + + if (fut->fut_callback0 == NULL) { + Py_INCREF(fut->fut_callbacks); + return fut->fut_callbacks; + } + + assert(fut->fut_callback0 != NULL); + + len = PyList_GET_SIZE(fut->fut_callbacks); + new_list = PyList_New(len + 1); + if (new_list == NULL) { + return NULL; + } + + Py_INCREF(fut->fut_callback0); + PyList_SET_ITEM(new_list, 0, fut->fut_callback0); + for (i = 0; i < len; i++) { + PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i); + Py_INCREF(cb); + PyList_SET_ITEM(new_list, i + 1, cb); } - Py_INCREF(fut->fut_callbacks); - return fut->fut_callbacks; + + return new_list; } static PyObject * FutureObj_get_result(FutureObj *fut) { + ENSURE_FUTURE_ALIVE(fut) if (fut->fut_result == NULL) { Py_RETURN_NONE; } @@ -834,6 +1032,7 @@ FutureObj_get_result(FutureObj *fut) static PyObject * FutureObj_get_exception(FutureObj *fut) { + ENSURE_FUTURE_ALIVE(fut) if (fut->fut_exception == NULL) { Py_RETURN_NONE; } @@ -844,7 +1043,7 @@ FutureObj_get_exception(FutureObj *fut) static PyObject * FutureObj_get_source_traceback(FutureObj *fut) { - if (fut->fut_source_tb == NULL) { + if (!future_is_alive(fut) || fut->fut_source_tb == NULL) { Py_RETURN_NONE; } Py_INCREF(fut->fut_source_tb); @@ -859,6 +1058,8 @@ FutureObj_get_state(FutureObj *fut) _Py_IDENTIFIER(FINISHED); PyObject *ret = NULL; + ENSURE_FUTURE_ALIVE(fut) + switch (fut->fut_state) { case STATE_PENDING: ret = _PyUnicode_FromId(&PyId_PENDING); @@ -896,6 +1097,8 @@ static PyObject * _asyncio_Future__schedule_callbacks_impl(FutureObj *self) /*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/ { + ENSURE_FUTURE_ALIVE(self) + int ret = future_schedule_callbacks(self); if (ret == -1) { return NULL; @@ -908,6 +1111,8 @@ FutureObj_repr(FutureObj *fut) { _Py_IDENTIFIER(_repr_info); + ENSURE_FUTURE_ALIVE(fut) + PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut, &PyId__repr_info, NULL); @@ -1068,12 +1273,10 @@ static PyTypeObject FutureType = { .tp_finalize = (destructor)FutureObj_finalize, }; -#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType) - static inline int future_call_schedule_callbacks(FutureObj *fut) { - if (Future_CheckExact(fut)) { + if (Future_CheckExact(fut) || Task_CheckExact(fut)) { return future_schedule_callbacks(fut); } else { @@ -1122,12 +1325,26 @@ typedef struct { FutureObj *future; } futureiterobject; + +#define FI_FREELIST_MAXLEN 255 +static futureiterobject *fi_freelist = NULL; +static Py_ssize_t fi_freelist_len = 0; + + static void FutureIter_dealloc(futureiterobject *it) { PyObject_GC_UnTrack(it); - Py_XDECREF(it->future); - PyObject_GC_Del(it); + Py_CLEAR(it->future); + + if (fi_freelist_len < FI_FREELIST_MAXLEN) { + fi_freelist_len++; + it->future = (FutureObj*) fi_freelist; + fi_freelist = it; + } + else { + PyObject_GC_Del(it); + } } static PyObject * @@ -1272,10 +1489,23 @@ future_new_iter(PyObject *fut) PyErr_BadInternalCall(); return NULL; } - it = PyObject_GC_New(futureiterobject, &FutureIterType); - if (it == NULL) { - return NULL; + + ENSURE_FUTURE_ALIVE(fut) + + if (fi_freelist_len) { + fi_freelist_len--; + it = fi_freelist; + fi_freelist = (futureiterobject*) it->future; + it->future = NULL; + _Py_NewReference((PyObject*) it); + } + else { + it = PyObject_GC_New(futureiterobject, &FutureIterType); + if (it == NULL) { + return NULL; + } } + Py_INCREF(fut); it->future = (FutureObj*)fut; PyObject_GC_Track(it); @@ -1549,20 +1779,25 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) /*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/ { PyObject *res; - int tmp; + if (future_init((FutureObj*)self, loop)) { return -1; } if (!PyCoro_CheckExact(coro)) { - // fastpath failed, perfom slow check - // raise after Future.__init__(), attrs are required for __del__ - res = PyObject_CallFunctionObjArgs(asyncio_iscoroutine_func, - coro, NULL); + /* 'coro' is not a native coroutine, call asyncio.iscoroutine() + to check if it's another coroutine flavour. + + Do this check after 'future_init()'; in case we need to raise + an error, __del__ needs a properly initialized object. + */ + res = PyObject_CallFunctionObjArgs( + asyncio_iscoroutine_func, coro, NULL); if (res == NULL) { return -1; } - tmp = PyObject_Not(res); + + int tmp = PyObject_Not(res); Py_DECREF(res); if (tmp < 0) { return -1; @@ -2023,8 +2258,6 @@ static PyTypeObject TaskType = { .tp_finalize = (destructor)TaskObj_finalize, }; -#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType) - static void TaskObj_dealloc(PyObject *self) { @@ -2079,22 +2312,14 @@ task_call_step(TaskObj *task, PyObject *arg) static int task_call_step_soon(TaskObj *task, PyObject *arg) { - PyObject *handle; - PyObject *cb = TaskStepMethWrapper_new(task, arg); if (cb == NULL) { return -1; } - handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon, - cb, NULL); + int ret = call_soon(task->task_loop, cb, NULL); Py_DECREF(cb); - if (handle == NULL) { - return -1; - } - - Py_DECREF(handle); - return 0; + return ret; } static PyObject * @@ -2746,6 +2971,26 @@ _asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task) /*********************** Module **************************/ +static void +module_free_freelists() +{ + PyObject *next; + PyObject *current; + + next = (PyObject*) fi_freelist; + while (next != NULL) { + assert(fi_freelist_len > 0); + fi_freelist_len--; + + current = next; + next = (PyObject*) ((futureiterobject*) current)->future; + PyObject_GC_Del(current); + } + assert(fi_freelist_len == 0); + fi_freelist = NULL; +} + + static void module_free(void *m) { @@ -2764,6 +3009,8 @@ module_free(void *m) Py_CLEAR(current_tasks); Py_CLEAR(all_tasks); + + module_free_freelists(); } static int From webhook-mailer at python.org Sun Dec 17 23:10:20 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 18 Dec 2017 04:10:20 -0000 Subject: [Python-checkins] bpo-30050: Allow disabling full buffer warnings in signal.set_wakeup_fd (#4792) Message-ID: https://github.com/python/cpython/commit/902ab80b590e474bb2077b1fae8aac497b856d66 commit: 902ab80b590e474bb2077b1fae8aac497b856d66 branch: master author: Nathaniel J. Smith committer: Yury Selivanov date: 2017-12-17T23:10:18-05:00 summary: bpo-30050: Allow disabling full buffer warnings in signal.set_wakeup_fd (#4792) files: A Misc/NEWS.d/next/Library/2017-12-10-23-44-56.bpo-30050.4SZ3lY.rst M Doc/library/signal.rst M Lib/test/test_signal.py M Modules/signalmodule.c diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index 2bc39d9f133..67eaa2c6381 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -300,7 +300,7 @@ The :mod:`signal` module defines the following functions: Availability: Unix. -.. function:: set_wakeup_fd(fd) +.. function:: set_wakeup_fd(fd, *, warn_on_full_buffer=True) Set the wakeup file descriptor to *fd*. When a signal is received, the signal number is written as a single byte into the fd. This can be used by @@ -312,16 +312,36 @@ The :mod:`signal` module defines the following functions: If not -1, *fd* must be non-blocking. It is up to the library to remove any bytes from *fd* before calling poll or select again. - Use for example ``struct.unpack('%uB' % len(data), data)`` to decode the - signal numbers list. - When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a :exc:`ValueError` exception to be raised. + There are two common ways to use this function. In both approaches, + you use the fd to wake up when a signal arrives, but then they + differ in how they determine *which* signal or signals have + arrived. + + In the first approach, we read the data out of the fd's buffer, and + the byte values give you the signal numbers. This is simple, but in + rare cases it can run into a problem: generally the fd will have a + limited amount of buffer space, and if too many signals arrive too + quickly, then the buffer may become full, and some signals may be + lost. If you use this approach, then you should set + ``warn_on_full_buffer=True``, which will at least cause a warning + to be printed to stderr when signals are lost. + + In the second approach, we use the wakeup fd *only* for wakeups, + and ignore the actual byte values. In this case, all we care about + is whether the fd's buffer is empty or non-empty; a full buffer + doesn't indicate a problem at all. If you use this approach, then + you should set ``warn_on_full_buffer=False``, so that your users + are not confused by spurious warning messages. + .. versionchanged:: 3.5 On Windows, the function now also supports socket handles. + .. versionchanged:: 3.7 + Added ``warn_on_full_buffer`` parameter. .. function:: siginterrupt(signalnum, flag) diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index dc048e56665..f17123c3bb5 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -91,6 +91,15 @@ def test_issue9324(self): class WakeupFDTests(unittest.TestCase): + def test_invalid_call(self): + # First parameter is positional-only + with self.assertRaises(TypeError): + signal.set_wakeup_fd(signum=signal.SIGINT) + + # warn_on_full_buffer is a keyword-only parameter + with self.assertRaises(TypeError): + signal.set_wakeup_fd(signal.SIGINT, False) + def test_invalid_fd(self): fd = support.make_bad_fd() self.assertRaises((ValueError, OSError), @@ -423,6 +432,89 @@ def handler(signum, frame): """.format(action=action) assert_python_ok('-c', code) + @unittest.skipIf(_testcapi is None, 'need _testcapi') + def test_warn_on_full_buffer(self): + # Use a subprocess to have only one thread. + if os.name == 'nt': + action = 'send' + else: + action = 'write' + code = """if 1: + import errno + import signal + import socket + import sys + import time + import _testcapi + from test.support import captured_stderr + + signum = signal.SIGINT + + # This handler will be called, but we intentionally won't read from + # the wakeup fd. + def handler(signum, frame): + pass + + signal.signal(signum, handler) + + read, write = socket.socketpair() + read.setblocking(False) + write.setblocking(False) + + # Fill the send buffer + try: + while True: + write.send(b"x") + except BlockingIOError: + pass + + # By default, we get a warning when a signal arrives + signal.set_wakeup_fd(write.fileno()) + + with captured_stderr() as err: + _testcapi.raise_signal(signum) + + err = err.getvalue() + if ('Exception ignored when trying to {action} to the signal wakeup fd' + not in err): + raise AssertionError(err) + + # And also if warn_on_full_buffer=True + signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=True) + + with captured_stderr() as err: + _testcapi.raise_signal(signum) + + err = err.getvalue() + if ('Exception ignored when trying to {action} to the signal wakeup fd' + not in err): + raise AssertionError(err) + + # But not if warn_on_full_buffer=False + signal.set_wakeup_fd(write.fileno(), warn_on_full_buffer=False) + + with captured_stderr() as err: + _testcapi.raise_signal(signum) + + err = err.getvalue() + if err != "": + raise AssertionError("got unexpected output %r" % (err,)) + + # And then check the default again, to make sure warn_on_full_buffer + # settings don't leak across calls. + signal.set_wakeup_fd(write.fileno()) + + with captured_stderr() as err: + _testcapi.raise_signal(signum) + + err = err.getvalue() + if ('Exception ignored when trying to {action} to the signal wakeup fd' + not in err): + raise AssertionError(err) + + """.format(action=action) + assert_python_ok('-c', code) + @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") class SiginterruptTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2017-12-10-23-44-56.bpo-30050.4SZ3lY.rst b/Misc/NEWS.d/next/Library/2017-12-10-23-44-56.bpo-30050.4SZ3lY.rst new file mode 100644 index 00000000000..76de12bbe80 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-10-23-44-56.bpo-30050.4SZ3lY.rst @@ -0,0 +1,3 @@ +New argument warn_on_full_buffer to signal.set_wakeup_fd lets you control +whether Python prints a warning on stderr when the wakeup fd buffer +overflows. diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 1023244b626..b553eedc0f2 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -100,14 +100,15 @@ static volatile struct { static volatile struct { SOCKET_T fd; + int warn_on_full_buffer; int use_send; - int send_err_set; - int send_errno; - int send_win_error; -} wakeup = {INVALID_FD, 0, 0}; +} wakeup = {.fd = INVALID_FD, .warn_on_full_buffer = 1, .use_send = 0}; #else #define INVALID_FD (-1) -static volatile sig_atomic_t wakeup_fd = -1; +static volatile struct { + sig_atomic_t fd; + int warn_on_full_buffer; +} wakeup = {.fd = INVALID_FD, .warn_on_full_buffer = 1}; #endif /* Speed up sigcheck() when none tripped */ @@ -210,28 +211,15 @@ report_wakeup_write_error(void *data) #ifdef MS_WINDOWS static int -report_wakeup_send_error(void* Py_UNUSED(data)) +report_wakeup_send_error(void* data) { - PyObject *res; - - if (wakeup.send_win_error) { - /* PyErr_SetExcFromWindowsErr() invokes FormatMessage() which - recognizes the error codes used by both GetLastError() and - WSAGetLastError */ - res = PyErr_SetExcFromWindowsErr(PyExc_OSError, wakeup.send_win_error); - } - else { - errno = wakeup.send_errno; - res = PyErr_SetFromErrno(PyExc_OSError); - } - - assert(res == NULL); - wakeup.send_err_set = 0; - + /* PyErr_SetExcFromWindowsErr() invokes FormatMessage() which + recognizes the error codes used by both GetLastError() and + WSAGetLastError */ + PyErr_SetExcFromWindowsErr(PyExc_OSError, (int) (intptr_t) data); PySys_WriteStderr("Exception ignored when trying to send to the " "signal wakeup fd:\n"); PyErr_WriteUnraisable(NULL); - return 0; } #endif /* MS_WINDOWS */ @@ -257,7 +245,7 @@ trip_signal(int sig_num) and then set the flag, but this allowed the following sequence of events (especially on windows, where trip_signal may run in a new thread): - - main thread blocks on select([wakeup_fd], ...) + - main thread blocks on select([wakeup.fd], ...) - signal arrives - trip_signal writes to the wakeup fd - the main thread wakes up @@ -274,41 +262,43 @@ trip_signal(int sig_num) #ifdef MS_WINDOWS fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int); #else - fd = wakeup_fd; + fd = wakeup.fd; #endif if (fd != INVALID_FD) { byte = (unsigned char)sig_num; #ifdef MS_WINDOWS if (wakeup.use_send) { - do { - rc = send(fd, &byte, 1, 0); - } while (rc < 0 && errno == EINTR); - - /* we only have a storage for one error in the wakeup structure */ - if (rc < 0 && !wakeup.send_err_set) { - wakeup.send_err_set = 1; - wakeup.send_errno = errno; - wakeup.send_win_error = GetLastError(); - /* Py_AddPendingCall() isn't signal-safe, but we - still use it for this exceptional case. */ - Py_AddPendingCall(report_wakeup_send_error, NULL); + rc = send(fd, &byte, 1, 0); + + if (rc < 0) { + int last_error = GetLastError(); + if (wakeup.warn_on_full_buffer || + last_error != WSAEWOULDBLOCK) + { + /* Py_AddPendingCall() isn't signal-safe, but we + still use it for this exceptional case. */ + Py_AddPendingCall(report_wakeup_send_error, + (void *)(intptr_t) last_error); + } } } else #endif { - byte = (unsigned char)sig_num; - /* _Py_write_noraise() retries write() if write() is interrupted by a signal (fails with EINTR). */ rc = _Py_write_noraise(fd, &byte, 1); if (rc < 0) { - /* Py_AddPendingCall() isn't signal-safe, but we - still use it for this exceptional case. */ - Py_AddPendingCall(report_wakeup_write_error, - (void *)(intptr_t)errno); + if (wakeup.warn_on_full_buffer || + (errno != EWOULDBLOCK && errno != EAGAIN)) + { + /* Py_AddPendingCall() isn't signal-safe, but we + still use it for this exceptional case. */ + Py_AddPendingCall(report_wakeup_write_error, + (void *)(intptr_t)errno); + } } } } @@ -549,9 +539,13 @@ signal_siginterrupt_impl(PyObject *module, int signalnum, int flag) static PyObject* -signal_set_wakeup_fd(PyObject *self, PyObject *args) +signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds) { struct _Py_stat_struct status; + static char *kwlist[] = { + "", "warn_on_full_buffer", NULL, + }; + int warn_on_full_buffer = 1; #ifdef MS_WINDOWS PyObject *fdobj; SOCKET_T sockfd, old_sockfd; @@ -560,7 +554,8 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args) PyObject *mod; int is_socket; - if (!PyArg_ParseTuple(args, "O:set_wakeup_fd", &fdobj)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|$p:set_wakeup_fd", kwlist, + &fdobj, &warn_on_full_buffer)) return NULL; sockfd = PyLong_AsSocket_t(fdobj); @@ -569,7 +564,8 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args) #else int fd, old_fd; - if (!PyArg_ParseTuple(args, "i:set_wakeup_fd", &fd)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|$p:set_wakeup_fd", kwlist, + &fd, &warn_on_full_buffer)) return NULL; #endif @@ -620,6 +616,7 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args) old_sockfd = wakeup.fd; wakeup.fd = sockfd; + wakeup.warn_on_full_buffer = warn_on_full_buffer; wakeup.use_send = is_socket; if (old_sockfd != INVALID_FD) @@ -644,15 +641,16 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args) } } - old_fd = wakeup_fd; - wakeup_fd = fd; + old_fd = wakeup.fd; + wakeup.fd = fd; + wakeup.warn_on_full_buffer = warn_on_full_buffer; return PyLong_FromLong(old_fd); #endif } PyDoc_STRVAR(set_wakeup_fd_doc, -"set_wakeup_fd(fd) -> fd\n\ +"set_wakeup_fd(fd, *, warn_on_full_buffer=True) -> fd\n\ \n\ Sets the fd to be written to (with the signal number) when a signal\n\ comes in. A library can use this to wakeup select or poll.\n\ @@ -670,11 +668,11 @@ PySignal_SetWakeupFd(int fd) #ifdef MS_WINDOWS old_fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int); - wakeup.fd = fd; #else - old_fd = wakeup_fd; - wakeup_fd = fd; + old_fd = wakeup.fd; #endif + wakeup.fd = fd; + wakeup.warn_on_full_buffer = 1; return old_fd; } @@ -1155,7 +1153,7 @@ static PyMethodDef signal_methods[] = { SIGNAL_GETITIMER_METHODDEF SIGNAL_SIGNAL_METHODDEF SIGNAL_GETSIGNAL_METHODDEF - {"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc}, + {"set_wakeup_fd", (PyCFunction)signal_set_wakeup_fd, METH_VARARGS | METH_KEYWORDS, set_wakeup_fd_doc}, SIGNAL_SIGINTERRUPT_METHODDEF SIGNAL_PAUSE_METHODDEF SIGNAL_PTHREAD_KILL_METHODDEF From webhook-mailer at python.org Mon Dec 18 01:52:57 2017 From: webhook-mailer at python.org (INADA Naoki) Date: Mon, 18 Dec 2017 06:52:57 -0000 Subject: [Python-checkins] bpo-29469: peephole: Remove const_stack (GH-4879) Message-ID: https://github.com/python/cpython/commit/87010e85cb37192d63b1a30e5fabba307ad5a3f5 commit: 87010e85cb37192d63b1a30e5fabba307ad5a3f5 branch: master author: INADA Naoki committer: GitHub date: 2017-12-18T15:52:54+09:00 summary: bpo-29469: peephole: Remove const_stack (GH-4879) Constant folding was moved to AST optimizer. But compiler may emit LOAD_CONSTs + BUILD_TUPLE. For example, default arguments can be constant tuple if all arguments are constant. This commit makes peephole's tuple folding simple. It doesn't support nested tuples because nested tuples are folded by AST optimizer already. files: M Python/peephole.c diff --git a/Python/peephole.c b/Python/peephole.c index 49d62a2c342..76a0edbcc2b 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -23,51 +23,6 @@ (blocks[start]==blocks[end]) -#define CONST_STACK_CREATE() { \ - const_stack_size = 256; \ - const_stack = PyMem_New(PyObject *, const_stack_size); \ - if (!const_stack) { \ - PyErr_NoMemory(); \ - goto exitError; \ - } \ - } - -#define CONST_STACK_DELETE() do { \ - if (const_stack) \ - PyMem_Free(const_stack); \ - } while(0) - -#define CONST_STACK_LEN() ((unsigned)(const_stack_top + 1)) - -#define CONST_STACK_PUSH_OP(i) do { \ - PyObject *_x; \ - assert(_Py_OPCODE(codestr[i]) == LOAD_CONST); \ - assert(PyList_GET_SIZE(consts) > (Py_ssize_t)get_arg(codestr, i)); \ - _x = PyList_GET_ITEM(consts, get_arg(codestr, i)); \ - if (++const_stack_top >= const_stack_size) { \ - const_stack_size *= 2; \ - PyMem_Resize(const_stack, PyObject *, const_stack_size); \ - if (!const_stack) { \ - PyErr_NoMemory(); \ - goto exitError; \ - } \ - } \ - const_stack[const_stack_top] = _x; \ - in_consts = 1; \ - } while(0) - -#define CONST_STACK_RESET() do { \ - const_stack_top = -1; \ - } while(0) - -#define CONST_STACK_LASTN(i) \ - &const_stack[CONST_STACK_LEN() - i] - -#define CONST_STACK_POP(i) do { \ - assert(CONST_STACK_LEN() >= i); \ - const_stack_top -= i; \ - } while(0) - /* Scans back N consecutive LOAD_CONST instructions, skipping NOPs, returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix. Callers are responsible to check CONST_STACK_LEN beforehand. @@ -88,8 +43,7 @@ lastn_const_start(const _Py_CODEUNIT *codestr, Py_ssize_t i, Py_ssize_t n) } } else { - assert(_Py_OPCODE(codestr[i]) == NOP || - _Py_OPCODE(codestr[i]) == EXTENDED_ARG); + assert(_Py_OPCODE(codestr[i]) == EXTENDED_ARG); } } } @@ -172,39 +126,40 @@ copy_op_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned char op, The consts table must still be in list form so that the new constant (c1, c2, ... cn) can be appended. Called with codestr pointing to the first LOAD_CONST. - Bails out with no change if one or more of the LOAD_CONSTs is missing. */ static Py_ssize_t fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, - Py_ssize_t opcode_end, unsigned char opcode, - PyObject *consts, PyObject **objs, int n) + Py_ssize_t opcode_end, PyObject *consts, int n) { - PyObject *newconst, *constant; - Py_ssize_t i, len_consts; - /* Pre-conditions */ assert(PyList_CheckExact(consts)); /* Buildup new tuple of constants */ - newconst = PyTuple_New(n); + PyObject *newconst = PyTuple_New(n); if (newconst == NULL) { return -1; } - for (i=0 ; i 0 && CONST_STACK_LEN() >= j) { + if (j > 0 && lastlc >= j) { h = lastn_const_start(codestr, op_start, j); if (ISBASICBLOCK(blocks, h, op_start)) { - h = fold_tuple_on_constants(codestr, h, i + 1, opcode, - consts, CONST_STACK_LASTN(j), j); - if (h >= 0) { - CONST_STACK_POP(j); - CONST_STACK_PUSH_OP(h); - } + h = fold_tuple_on_constants(codestr, h, i+1, consts, j); break; } } @@ -374,12 +318,10 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } else if (j == 2) { codestr[op_start] = PACKOPARG(ROT_TWO, 0); fill_nops(codestr, op_start + 1, nexti + 1); - CONST_STACK_RESET(); } else if (j == 3) { codestr[op_start] = PACKOPARG(ROT_THREE, 0); codestr[op_start + 1] = PACKOPARG(ROT_TWO, 0); fill_nops(codestr, op_start + 2, nexti + 1); - CONST_STACK_RESET(); } break; @@ -538,7 +480,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } assert(h + (Py_ssize_t)nops == codelen); - CONST_STACK_DELETE(); PyMem_Free(blocks); code = PyBytes_FromStringAndSize((char *)codestr, h * sizeof(_Py_CODEUNIT)); PyMem_Free(codestr); @@ -549,7 +490,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, exitUnchanged: Py_XINCREF(code); - CONST_STACK_DELETE(); PyMem_Free(blocks); PyMem_Free(codestr); return code; From solipsis at pitrou.net Mon Dec 18 04:09:53 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 18 Dec 2017 09:09:53 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-1 Message-ID: <20171218090953.20216.8527E25188731D82@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 0] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [2, -1, 1] memory blocks, sum=2 test_multiprocessing_forkserver leaked [0, 1, -2] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogTogQ7f', '--timeout', '7200'] From webhook-mailer at python.org Mon Dec 18 04:28:28 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 18 Dec 2017 09:28:28 -0000 Subject: [Python-checkins] bpo-19764: Implemented support for subprocess.Popen(close_fds=True) on Windows (#1218) Message-ID: https://github.com/python/cpython/commit/b2a6083eb0384f38839d3f1ed32262a3852026fa commit: b2a6083eb0384f38839d3f1ed32262a3852026fa branch: master author: Segev Finer committer: Victor Stinner date: 2017-12-18T10:28:19+01:00 summary: bpo-19764: Implemented support for subprocess.Popen(close_fds=True) on Windows (#1218) Even though Python marks any handles it opens as non-inheritable there is still a race when using `subprocess.Popen` since creating a process with redirected stdio requires temporarily creating inheritable handles. By implementing support for `subprocess.Popen(close_fds=True)` we fix this race. In order to implement this we use PROC_THREAD_ATTRIBUTE_HANDLE_LIST which is available since Windows Vista. Which allows to pass an explicit list of handles to inherit when creating a process. This commit also adds `STARTUPINFO.lpAttributeList["handle_list"]` which can be used to control PROC_THREAD_ATTRIBUTE_HANDLE_LIST directly. files: A Misc/NEWS.d/next/Windows/2017-08-18-18-00-24.bpo-19764.ODpc9y.rst M Doc/library/subprocess.rst M Doc/whatsnew/3.7.rst M Lib/subprocess.py M Lib/test/test_subprocess.py M Misc/ACKS M Modules/_winapi.c M Modules/clinic/_winapi.c.h diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index a2c184a0460..af96f41ef40 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -452,17 +452,20 @@ functions. common use of *preexec_fn* to call os.setsid() in the child. If *close_fds* is true, all file descriptors except :const:`0`, :const:`1` and - :const:`2` will be closed before the child process is executed. (POSIX only). - The default varies by platform: Always true on POSIX. On Windows it is - true when *stdin*/*stdout*/*stderr* are :const:`None`, false otherwise. + :const:`2` will be closed before the child process is executed. On Windows, if *close_fds* is true then no handles will be inherited by the - child process. Note that on Windows, you cannot set *close_fds* to true and - also redirect the standard handles by setting *stdin*, *stdout* or *stderr*. + child process unless explicitly passed in the ``handle_list`` element of + :attr:`STARTUPINFO.lpAttributeList`, or by standard handle redirection. .. versionchanged:: 3.2 The default for *close_fds* was changed from :const:`False` to what is described above. + .. versionchanged:: 3.7 + On Windows the default for *close_fds* was changed from :const:`False` to + :const:`True` when redirecting the standard handles. It's now possible to + set *close_fds* to :const:`True` when redirecting the standard handles. + *pass_fds* is an optional sequence of file descriptors to keep open between the parent and child. Providing any *pass_fds* forces *close_fds* to be :const:`True`. (POSIX only) @@ -764,7 +767,7 @@ The :class:`STARTUPINFO` class and following constants are only available on Windows. .. class:: STARTUPINFO(*, dwFlags=0, hStdInput=None, hStdOutput=None, \ - hStdError=None, wShowWindow=0) + hStdError=None, wShowWindow=0, lpAttributeList=None) Partial support of the Windows `STARTUPINFO `__ @@ -814,6 +817,33 @@ on Windows. :data:`SW_HIDE` is provided for this attribute. It is used when :class:`Popen` is called with ``shell=True``. + .. attribute:: lpAttributeList + + A dictionary of additional attributes for process creation as given in + ``STARTUPINFOEX``, see + `UpdateProcThreadAttribute `__. + + Supported attributes: + + **handle_list** + Sequence of handles that will be inherited. *close_fds* must be true if + non-empty. + + The handles must be temporarily made inheritable by + :func:`os.set_handle_inheritable` when passed to the :class:`Popen` + constructor, else :class:`OSError` will be raised with Windows error + ``ERROR_INVALID_PARAMETER`` (87). + + .. warning:: + + In a multithreaded process, use caution to avoid leaking handles + that are marked inheritable when combining this feature with + concurrent calls to other process creation functions that inherit + all handles such as :func:`os.system`. This also applies to + standard handle redirection, which temporarily creates inheritable + handles. + + .. versionadded:: 3.7 Windows Constants ^^^^^^^^^^^^^^^^^ diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 3574b53ad18..82f7cc07043 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -437,6 +437,17 @@ string expression pattern for braced placeholders and non-braced placeholders separately. (Contributed by Barry Warsaw in :issue:`1198569`.) +subprocess +---------- + +On Windows the default for *close_fds* was changed from :const:`False` to +:const:`True` when redirecting the standard handles. It's now possible to set +*close_fds* to :const:`True` when redirecting the standard handles. See +:class:`subprocess.Popen`. + +This means that *close_fds* now defaults to :const:`True` on all supported +platforms. + sys --- @@ -883,6 +894,14 @@ Changes in the Python API .. _Unicode Technical Standard #18: https://unicode.org/reports/tr18/ +* On Windows the default for the *close_fds* argument of + :class:`subprocess.Popen` was changed from :const:`False` to :const:`True` + when redirecting the standard handles. If you previously depended on handles + being inherited when using :class:`subprocess.Popen` with standard io + redirection, you will have to pass ``close_fds=False`` to preserve the + previous behaviour, or use + :attr:`STARTUPINFO.lpAttributeList `. + Changes in the C API -------------------- diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 65b4086dc61..db6342fa491 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -128,12 +128,13 @@ def stdout(self, value): import _winapi class STARTUPINFO: def __init__(self, *, dwFlags=0, hStdInput=None, hStdOutput=None, - hStdError=None, wShowWindow=0): + hStdError=None, wShowWindow=0, lpAttributeList=None): self.dwFlags = dwFlags self.hStdInput = hStdInput self.hStdOutput = hStdOutput self.hStdError = hStdError self.wShowWindow = wShowWindow + self.lpAttributeList = lpAttributeList or {"handle_list": []} else: import _posixsubprocess import select @@ -577,9 +578,6 @@ def getoutput(cmd): return getstatusoutput(cmd)[1] -_PLATFORM_DEFAULT_CLOSE_FDS = object() - - class Popen(object): """ Execute a child program in a new process. @@ -630,7 +628,7 @@ class Popen(object): def __init__(self, args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS, + preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, @@ -655,21 +653,8 @@ def __init__(self, args, bufsize=-1, executable=None, if preexec_fn is not None: raise ValueError("preexec_fn is not supported on Windows " "platforms") - any_stdio_set = (stdin is not None or stdout is not None or - stderr is not None) - if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS: - if any_stdio_set: - close_fds = False - else: - close_fds = True - elif close_fds and any_stdio_set: - raise ValueError( - "close_fds is not supported on Windows platforms" - " if you redirect stdin/stdout/stderr") else: # POSIX - if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS: - close_fds = True if pass_fds and not close_fds: warnings.warn("pass_fds overriding close_fds.", RuntimeWarning) close_fds = True @@ -1019,6 +1004,19 @@ def _make_inheritable(self, handle): return Handle(h) + def _filter_handle_list(self, handle_list): + """Filter out console handles that can't be used + in lpAttributeList["handle_list"] and make sure the list + isn't empty. This also removes duplicate handles.""" + # An handle with it's lowest two bits set might be a special console + # handle that if passed in lpAttributeList["handle_list"], will + # cause it to fail. + return list({handle for handle in handle_list + if handle & 0x3 != 0x3 + or _winapi.GetFileType(handle) != + _winapi.FILE_TYPE_CHAR}) + + def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, @@ -1036,12 +1034,41 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, # Process startup details if startupinfo is None: startupinfo = STARTUPINFO() - if -1 not in (p2cread, c2pwrite, errwrite): + + use_std_handles = -1 not in (p2cread, c2pwrite, errwrite) + if use_std_handles: startupinfo.dwFlags |= _winapi.STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite + attribute_list = startupinfo.lpAttributeList + have_handle_list = bool(attribute_list and + "handle_list" in attribute_list and + attribute_list["handle_list"]) + + # If we were given an handle_list or need to create one + if have_handle_list or (use_std_handles and close_fds): + if attribute_list is None: + attribute_list = startupinfo.lpAttributeList = {} + handle_list = attribute_list["handle_list"] = \ + list(attribute_list.get("handle_list", [])) + + if use_std_handles: + handle_list += [int(p2cread), int(c2pwrite), int(errwrite)] + + handle_list[:] = self._filter_handle_list(handle_list) + + if handle_list: + if not close_fds: + warnings.warn("startupinfo.lpAttributeList['handle_list'] " + "overriding close_fds", RuntimeWarning) + + # When using the handle_list we always request to inherit + # handles but the only handles that will be inherited are + # the ones in the handle_list + close_fds = False + if shell: startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW startupinfo.wShowWindow = _winapi.SW_HIDE diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index fff1b0db105..bd3b9b46f76 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -2743,11 +2743,6 @@ def test_invalid_args(self): [sys.executable, "-c", "import sys; sys.exit(47)"], preexec_fn=lambda: 1) - self.assertRaises(ValueError, subprocess.call, - [sys.executable, "-c", - "import sys; sys.exit(47)"], - stdout=subprocess.PIPE, - close_fds=True) @support.cpython_only def test_issue31471(self): @@ -2765,6 +2760,67 @@ def test_close_fds(self): close_fds=True) self.assertEqual(rc, 47) + def test_close_fds_with_stdio(self): + import msvcrt + + fds = os.pipe() + self.addCleanup(os.close, fds[0]) + self.addCleanup(os.close, fds[1]) + + handles = [] + for fd in fds: + os.set_inheritable(fd, True) + handles.append(msvcrt.get_osfhandle(fd)) + + p = subprocess.Popen([sys.executable, "-c", + "import msvcrt; print(msvcrt.open_osfhandle({}, 0))".format(handles[0])], + stdout=subprocess.PIPE, close_fds=False) + stdout, stderr = p.communicate() + self.assertEqual(p.returncode, 0) + int(stdout.strip()) # Check that stdout is an integer + + p = subprocess.Popen([sys.executable, "-c", + "import msvcrt; print(msvcrt.open_osfhandle({}, 0))".format(handles[0])], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) + stdout, stderr = p.communicate() + self.assertEqual(p.returncode, 1) + self.assertIn(b"OSError", stderr) + + # The same as the previous call, but with an empty handle_list + handle_list = [] + startupinfo = subprocess.STARTUPINFO() + startupinfo.lpAttributeList = {"handle_list": handle_list} + p = subprocess.Popen([sys.executable, "-c", + "import msvcrt; print(msvcrt.open_osfhandle({}, 0))".format(handles[0])], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + startupinfo=startupinfo, close_fds=True) + stdout, stderr = p.communicate() + self.assertEqual(p.returncode, 1) + self.assertIn(b"OSError", stderr) + + # Check for a warning due to using handle_list and close_fds=False + with support.check_warnings((".*overriding close_fds", RuntimeWarning)): + startupinfo = subprocess.STARTUPINFO() + startupinfo.lpAttributeList = {"handle_list": handles[:]} + p = subprocess.Popen([sys.executable, "-c", + "import msvcrt; print(msvcrt.open_osfhandle({}, 0))".format(handles[0])], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + startupinfo=startupinfo, close_fds=False) + stdout, stderr = p.communicate() + self.assertEqual(p.returncode, 0) + + def test_empty_attribute_list(self): + startupinfo = subprocess.STARTUPINFO() + startupinfo.lpAttributeList = {} + subprocess.call([sys.executable, "-c", "import sys; sys.exit(0)"], + startupinfo=startupinfo) + + def test_empty_handle_list(self): + startupinfo = subprocess.STARTUPINFO() + startupinfo.lpAttributeList = {"handle_list": []} + subprocess.call([sys.executable, "-c", "import sys; sys.exit(0)"], + startupinfo=startupinfo) + def test_shell_sequence(self): # Run command through the shell (sequence) newenv = os.environ.copy() diff --git a/Misc/ACKS b/Misc/ACKS index 8303ce80050..e5343899640 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -466,6 +466,7 @@ Carl Feynman Vincent Fiack Anastasia Filatova Tomer Filiba +Segev Finer Jeffrey Finkelstein Russell Finn Dan Finnie diff --git a/Misc/NEWS.d/next/Windows/2017-08-18-18-00-24.bpo-19764.ODpc9y.rst b/Misc/NEWS.d/next/Windows/2017-08-18-18-00-24.bpo-19764.ODpc9y.rst new file mode 100644 index 00000000000..b5f5cae8323 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2017-08-18-18-00-24.bpo-19764.ODpc9y.rst @@ -0,0 +1,2 @@ +Implement support for `subprocess.Popen(close_fds=True)` on Windows. Patch +by Segev Finer. diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 604c05d4ae1..c596cba3cbc 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -811,6 +811,165 @@ getenvironment(PyObject* environment) return NULL; } +static LPHANDLE +gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size) +{ + LPHANDLE ret = NULL; + PyObject *value_fast = NULL; + PyObject *value; + Py_ssize_t i; + + value = PyMapping_GetItemString(mapping, name); + if (!value) { + PyErr_Clear(); + return NULL; + } + + if (value == Py_None) { + goto cleanup; + } + + value_fast = PySequence_Fast(value, "handle_list must be a sequence or None"); + if (value_fast == NULL) + goto cleanup; + + *size = PySequence_Fast_GET_SIZE(value_fast) * sizeof(HANDLE); + + /* Passing an empty array causes CreateProcess to fail so just don't set it */ + if (*size == 0) { + goto cleanup; + } + + ret = PyMem_Malloc(*size); + if (ret == NULL) + goto cleanup; + + for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) { + ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i)); + if (ret[i] == (HANDLE)-1 && PyErr_Occurred()) { + PyMem_Free(ret); + ret = NULL; + goto cleanup; + } + } + +cleanup: + Py_DECREF(value); + Py_XDECREF(value_fast); + return ret; +} + +typedef struct { + LPPROC_THREAD_ATTRIBUTE_LIST attribute_list; + LPHANDLE handle_list; +} AttributeList; + +static void +freeattributelist(AttributeList *attribute_list) +{ + if (attribute_list->attribute_list != NULL) { + DeleteProcThreadAttributeList(attribute_list->attribute_list); + PyMem_Free(attribute_list->attribute_list); + } + + PyMem_Free(attribute_list->handle_list); + + memset(attribute_list, 0, sizeof(*attribute_list)); +} + +static int +getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list) +{ + int ret = 0; + DWORD err; + BOOL result; + PyObject *value; + Py_ssize_t handle_list_size; + DWORD attribute_count = 0; + SIZE_T attribute_list_size = 0; + + value = PyObject_GetAttrString(obj, name); + if (!value) { + PyErr_Clear(); /* FIXME: propagate error? */ + return 0; + } + + if (value == Py_None) { + ret = 0; + goto cleanup; + } + + if (!PyMapping_Check(value)) { + ret = -1; + PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name); + goto cleanup; + } + + attribute_list->handle_list = gethandlelist(value, "handle_list", &handle_list_size); + if (attribute_list->handle_list == NULL && PyErr_Occurred()) { + ret = -1; + goto cleanup; + } + + if (attribute_list->handle_list != NULL) + ++attribute_count; + + /* Get how many bytes we need for the attribute list */ + result = InitializeProcThreadAttributeList(NULL, attribute_count, 0, &attribute_list_size); + if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + ret = -1; + PyErr_SetFromWindowsErr(GetLastError()); + goto cleanup; + } + + attribute_list->attribute_list = PyMem_Malloc(attribute_list_size); + if (attribute_list->attribute_list == NULL) { + ret = -1; + goto cleanup; + } + + result = InitializeProcThreadAttributeList( + attribute_list->attribute_list, + attribute_count, + 0, + &attribute_list_size); + if (!result) { + err = GetLastError(); + + /* So that we won't call DeleteProcThreadAttributeList */ + PyMem_Free(attribute_list->attribute_list); + attribute_list->attribute_list = NULL; + + ret = -1; + PyErr_SetFromWindowsErr(err); + goto cleanup; + } + + if (attribute_list->handle_list != NULL) { + result = UpdateProcThreadAttribute( + attribute_list->attribute_list, + 0, + PROC_THREAD_ATTRIBUTE_HANDLE_LIST, + attribute_list->handle_list, + handle_list_size, + NULL, + NULL); + if (!result) { + ret = -1; + PyErr_SetFromWindowsErr(GetLastError()); + goto cleanup; + } + } + +cleanup: + Py_DECREF(value); + + if (ret < 0) + freeattributelist(attribute_list); + + return ret; +} + /*[clinic input] _winapi.CreateProcess @@ -842,34 +1001,35 @@ _winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, PyObject *startup_info) /*[clinic end generated code: output=4652a33aff4b0ae1 input=4a43b05038d639bb]*/ { + PyObject *ret = NULL; BOOL result; PROCESS_INFORMATION pi; - STARTUPINFOW si; - PyObject* environment; + STARTUPINFOEXW si; + PyObject *environment = NULL; wchar_t *wenvironment; + AttributeList attribute_list = {0}; ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); + si.StartupInfo.cb = sizeof(si); /* note: we only support a small subset of all SI attributes */ - si.dwFlags = getulong(startup_info, "dwFlags"); - si.wShowWindow = (WORD)getulong(startup_info, "wShowWindow"); - si.hStdInput = gethandle(startup_info, "hStdInput"); - si.hStdOutput = gethandle(startup_info, "hStdOutput"); - si.hStdError = gethandle(startup_info, "hStdError"); + si.StartupInfo.dwFlags = getulong(startup_info, "dwFlags"); + si.StartupInfo.wShowWindow = (WORD)getulong(startup_info, "wShowWindow"); + si.StartupInfo.hStdInput = gethandle(startup_info, "hStdInput"); + si.StartupInfo.hStdOutput = gethandle(startup_info, "hStdOutput"); + si.StartupInfo.hStdError = gethandle(startup_info, "hStdError"); if (PyErr_Occurred()) - return NULL; + goto cleanup; if (env_mapping != Py_None) { environment = getenvironment(env_mapping); if (environment == NULL) { - return NULL; + goto cleanup; } /* contains embedded null characters */ wenvironment = PyUnicode_AsUnicode(environment); if (wenvironment == NULL) { - Py_DECREF(environment); - return NULL; + goto cleanup; } } else { @@ -877,29 +1037,41 @@ _winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, wenvironment = NULL; } + if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0) + goto cleanup; + + si.lpAttributeList = attribute_list.attribute_list; + Py_BEGIN_ALLOW_THREADS result = CreateProcessW(application_name, command_line, NULL, NULL, inherit_handles, - creation_flags | CREATE_UNICODE_ENVIRONMENT, + creation_flags | EXTENDED_STARTUPINFO_PRESENT | + CREATE_UNICODE_ENVIRONMENT, wenvironment, current_directory, - &si, + (LPSTARTUPINFOW)&si, &pi); Py_END_ALLOW_THREADS - Py_XDECREF(environment); + if (!result) { + PyErr_SetFromWindowsErr(GetLastError()); + goto cleanup; + } - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); + ret = Py_BuildValue("NNkk", + HANDLE_TO_PYNUM(pi.hProcess), + HANDLE_TO_PYNUM(pi.hThread), + pi.dwProcessId, + pi.dwThreadId); - return Py_BuildValue("NNkk", - HANDLE_TO_PYNUM(pi.hProcess), - HANDLE_TO_PYNUM(pi.hThread), - pi.dwProcessId, - pi.dwThreadId); +cleanup: + Py_XDECREF(environment); + freeattributelist(&attribute_list); + + return ret; } /*[clinic input] @@ -1489,7 +1661,6 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer, return Py_BuildValue("II", written, err); } - /*[clinic input] _winapi.GetACP @@ -1503,6 +1674,30 @@ _winapi_GetACP_impl(PyObject *module) return PyLong_FromUnsignedLong(GetACP()); } +/*[clinic input] +_winapi.GetFileType -> DWORD + + handle: HANDLE +[clinic start generated code]*/ + +static DWORD +_winapi_GetFileType_impl(PyObject *module, HANDLE handle) +/*[clinic end generated code: output=92b8466ac76ecc17 input=0058366bc40bbfbf]*/ +{ + DWORD result; + + Py_BEGIN_ALLOW_THREADS + result = GetFileType(handle); + Py_END_ALLOW_THREADS + + if (result == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) { + PyErr_SetFromWindowsErr(0); + return -1; + } + + return result; +} + static PyMethodDef winapi_functions[] = { _WINAPI_CLOSEHANDLE_METHODDEF @@ -1530,6 +1725,7 @@ static PyMethodDef winapi_functions[] = { _WINAPI_WAITFORSINGLEOBJECT_METHODDEF _WINAPI_WRITEFILE_METHODDEF _WINAPI_GETACP_METHODDEF + _WINAPI_GETFILETYPE_METHODDEF {NULL, NULL} }; @@ -1623,6 +1819,12 @@ PyInit__winapi(void) WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE); WINAPI_CONSTANT(F_DWORD, CREATE_BREAKAWAY_FROM_JOB); + WINAPI_CONSTANT(F_DWORD, FILE_TYPE_UNKNOWN); + WINAPI_CONSTANT(F_DWORD, FILE_TYPE_DISK); + WINAPI_CONSTANT(F_DWORD, FILE_TYPE_CHAR); + WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE); + WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE); + WINAPI_CONSTANT("i", NULL); return m; diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h index 80edbf58a20..b14f087732e 100644 --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -907,4 +907,38 @@ _winapi_GetACP(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _winapi_GetACP_impl(module); } -/*[clinic end generated code: output=b9c00c323c9f4944 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_winapi_GetFileType__doc__, +"GetFileType($module, /, handle)\n" +"--\n" +"\n"); + +#define _WINAPI_GETFILETYPE_METHODDEF \ + {"GetFileType", (PyCFunction)_winapi_GetFileType, METH_FASTCALL|METH_KEYWORDS, _winapi_GetFileType__doc__}, + +static DWORD +_winapi_GetFileType_impl(PyObject *module, HANDLE handle); + +static PyObject * +_winapi_GetFileType(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"handle", NULL}; + static _PyArg_Parser _parser = {"" F_HANDLE ":GetFileType", _keywords, 0}; + HANDLE handle; + DWORD _return_value; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &handle)) { + goto exit; + } + _return_value = _winapi_GetFileType_impl(module, handle); + if ((_return_value == PY_DWORD_MAX) && PyErr_Occurred()) { + goto exit; + } + return_value = Py_BuildValue("k", _return_value); + +exit: + return return_value; +} +/*[clinic end generated code: output=ec7f36eb7efc9d00 input=a9049054013a1b77]*/ From webhook-mailer at python.org Mon Dec 18 07:29:17 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 18 Dec 2017 12:29:17 -0000 Subject: [Python-checkins] bpo-32365: Fix a reference leak when compile __debug__. (#4916) Message-ID: https://github.com/python/cpython/commit/bd6ec4d79e8575df3d08f8a89ba721930032714c commit: bd6ec4d79e8575df3d08f8a89ba721930032714c branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-18T14:29:12+02:00 summary: bpo-32365: Fix a reference leak when compile __debug__. (#4916) It was introduced in bpo-27169. files: M Python/compile.c diff --git a/Python/compile.c b/Python/compile.c index 51c9a08162c..392de40f20a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3094,10 +3094,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) PyObject *mangled; /* XXX AugStore isn't used anywhere! */ - mangled = _Py_Mangle(c->u->u_private, name); - if (!mangled) - return 0; - assert(!_PyUnicode_EqualToASCIIString(name, "None") && !_PyUnicode_EqualToASCIIString(name, "True") && !_PyUnicode_EqualToASCIIString(name, "False")); @@ -3107,6 +3103,10 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) return 1; } + mangled = _Py_Mangle(c->u->u_private, name); + if (!mangled) + return 0; + op = 0; optype = OP_NAME; scope = PyST_GetScope(c->u->u_ste, mangled); From webhook-mailer at python.org Mon Dec 18 08:11:58 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 18 Dec 2017 13:11:58 -0000 Subject: [Python-checkins] bpo-32365: Fix a reference leak when compile __debug__. (GH-4916) (#4918) Message-ID: https://github.com/python/cpython/commit/5659743b5693c9e23313a74117948294e35013f4 commit: 5659743b5693c9e23313a74117948294e35013f4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-18T15:11:51+02:00 summary: bpo-32365: Fix a reference leak when compile __debug__. (GH-4916) (#4918) It was introduced in bpo-27169. (cherry picked from commit bd6ec4d79e8575df3d08f8a89ba721930032714c) files: M Python/compile.c diff --git a/Python/compile.c b/Python/compile.c index 13b4fb83076..3b8f9bbd442 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3032,10 +3032,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) PyObject *mangled; /* XXX AugStore isn't used anywhere! */ - mangled = _Py_Mangle(c->u->u_private, name); - if (!mangled) - return 0; - assert(!_PyUnicode_EqualToASCIIString(name, "None") && !_PyUnicode_EqualToASCIIString(name, "True") && !_PyUnicode_EqualToASCIIString(name, "False")); @@ -3045,6 +3041,10 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) return 1; } + mangled = _Py_Mangle(c->u->u_private, name); + if (!mangled) + return 0; + op = 0; optype = OP_NAME; scope = PyST_GetScope(c->u->u_ste, mangled); From webhook-mailer at python.org Mon Dec 18 11:20:44 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 18 Dec 2017 16:20:44 -0000 Subject: [Python-checkins] Add @asvetlov to asyncio codeowners (#4917) Message-ID: https://github.com/python/cpython/commit/02e4b7f35419a632b21d17435a61729b97ca0804 commit: 02e4b7f35419a632b21d17435a61729b97ca0804 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-18T18:20:42+02:00 summary: Add @asvetlov to asyncio codeowners (#4917) files: M .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3511dcf94a1..d751a918d0d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,7 +5,7 @@ # https://git-scm.com/docs/gitignore#_pattern_format # asyncio -**/*asyncio* @1st1 +**/*asyncio* @1st1 @asvetlov # Core **/*genobject* @1st1 From webhook-mailer at python.org Mon Dec 18 15:26:54 2017 From: webhook-mailer at python.org (Gregory P. Smith) Date: Mon, 18 Dec 2017 20:26:54 -0000 Subject: [Python-checkins] bpo-32369: test_subprocess: Fix pass_fds check in test_close_fds() (#4920) Message-ID: https://github.com/python/cpython/commit/2d8f06382e7d5a759ca554110a699a397114824a commit: 2d8f06382e7d5a759ca554110a699a397114824a branch: master author: izbyshev committer: Gregory P. Smith date: 2017-12-18T12:26:49-08:00 summary: bpo-32369: test_subprocess: Fix pass_fds check in test_close_fds() (#4920) The last part of test_close_fds() doesn't match its own comment. The following assertion always holds because fds_to_keep and open_fds are disjoint by construction. self.assertFalse(remaining_fds & fds_to_keep & open_fds, "Some fds not in pass_fds were left open") Fix the code to match the message in the assertion. files: M Lib/test/test_subprocess.py diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index bd3b9b46f76..540ad34d3f5 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -2290,11 +2290,11 @@ def test_close_fds(self): fds_to_keep = set(open_fds.pop() for _ in range(8)) p = subprocess.Popen([sys.executable, fd_status], stdout=subprocess.PIPE, close_fds=True, - pass_fds=()) + pass_fds=fds_to_keep) output, ignored = p.communicate() remaining_fds = set(map(int, output.split(b','))) - self.assertFalse(remaining_fds & fds_to_keep & open_fds, + self.assertFalse((remaining_fds - fds_to_keep) & open_fds, "Some fds not in pass_fds were left open") self.assertIn(1, remaining_fds, "Subprocess failed") From webhook-mailer at python.org Mon Dec 18 17:03:30 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 18 Dec 2017 22:03:30 -0000 Subject: [Python-checkins] bpo-32356: idempotent pause_/resume_reading; new is_reading method. (#4914) Message-ID: https://github.com/python/cpython/commit/d757aaf9dd767d13205bf9917e520ebf43e7f6e5 commit: d757aaf9dd767d13205bf9917e520ebf43e7f6e5 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-18T17:03:23-05:00 summary: bpo-32356: idempotent pause_/resume_reading; new is_reading method. (#4914) files: A Misc/NEWS.d/next/Library/2017-12-17-22-50-51.bpo-32356.roZJpA.rst M Doc/library/asyncio-protocol.rst M Lib/asyncio/proactor_events.py M Lib/asyncio/selector_events.py M Lib/asyncio/sslproto.py M Lib/asyncio/transports.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_selector_events.py M Lib/test/test_asyncio/utils.py diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index a4b0d594933..3aa1f2f2e99 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -118,17 +118,31 @@ ReadTransport Interface for read-only transports. + .. method:: is_reading() + + Return ``True`` if the transport is receiving new data. + + .. versionadded:: 3.7 + .. method:: pause_reading() Pause the receiving end of the transport. No data will be passed to the protocol's :meth:`data_received` method until :meth:`resume_reading` is called. + .. versionchanged:: 3.7 + The method is idempotent, i.e. it can be called when the + transport is already paused or closed. + .. method:: resume_reading() Resume the receiving end. The protocol's :meth:`data_received` method will be called once again if some data is available for reading. + .. versionchanged:: 3.7 + The method is idempotent, i.e. it can be called when the + transport is already reading. + WriteTransport -------------- diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 291d989cc45..915ad1ae91c 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -152,21 +152,20 @@ def __init__(self, loop, sock, protocol, waiter=None, self._paused = False self._loop.call_soon(self._loop_reading) + def is_reading(self): + return not self._paused and not self._closing + def pause_reading(self): - if self._closing: - raise RuntimeError('Cannot pause_reading() when closing') - if self._paused: - raise RuntimeError('Already paused') + if self._closing or self._paused: + return self._paused = True if self._loop.get_debug(): logger.debug("%r pauses reading", self) def resume_reading(self): - if not self._paused: - raise RuntimeError('Not paused') - self._paused = False - if self._closing: + if self._closing or not self._paused: return + self._paused = False self._loop.call_soon(self._loop_reading, self._read_fut) if self._loop.get_debug(): logger.debug("%r resumes reading", self) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index cb33cd34b87..3f44a998b89 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -702,22 +702,21 @@ def __init__(self, loop, sock, protocol, waiter=None, self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) + def is_reading(self): + return not self._paused and not self._closing + def pause_reading(self): - if self._closing: - raise RuntimeError('Cannot pause_reading() when closing') - if self._paused: - raise RuntimeError('Already paused') + if self._closing or self._paused: + return self._paused = True self._loop._remove_reader(self._sock_fd) if self._loop.get_debug(): logger.debug("%r pauses reading", self) def resume_reading(self): - if not self._paused: - raise RuntimeError('Not paused') - self._paused = False - if self._closing: + if self._closing or not self._paused: return + self._paused = False self._loop._add_reader(self._sock_fd, self._read_ready) if self._loop.get_debug(): logger.debug("%r resumes reading", self) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 0c8f01ad8f1..8da8570d66d 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -317,6 +317,12 @@ def __del__(self): source=self) self.close() + def is_reading(self): + tr = self._ssl_protocol._transport + if tr is None: + raise RuntimeError('SSL transport has not been initialized yet') + return tr.is_reading() + def pause_reading(self): """Pause the receiving end. diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py index 51f56737c67..233bbb53cb6 100644 --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -44,6 +44,10 @@ def get_protocol(self): class ReadTransport(BaseTransport): """Interface for read-only transports.""" + def is_reading(self): + """Return True if the transport is receiving.""" + raise NotImplementedError + def pause_reading(self): """Pause the receiving end. diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 910f2596620..47ebcad238c 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -334,26 +334,36 @@ def test_pause_resume_reading(self): f = asyncio.Future(loop=self.loop) f.set_result(msg) futures.append(f) + self.loop._proactor.recv.side_effect = futures self.loop._run_once() self.assertFalse(tr._paused) + self.assertTrue(tr.is_reading()) self.loop._run_once() self.protocol.data_received.assert_called_with(b'data1') self.loop._run_once() self.protocol.data_received.assert_called_with(b'data2') + + tr.pause_reading() tr.pause_reading() self.assertTrue(tr._paused) + self.assertFalse(tr.is_reading()) for i in range(10): self.loop._run_once() self.protocol.data_received.assert_called_with(b'data2') + + tr.resume_reading() tr.resume_reading() self.assertFalse(tr._paused) + self.assertTrue(tr.is_reading()) self.loop._run_once() self.protocol.data_received.assert_called_with(b'data3') self.loop._run_once() self.protocol.data_received.assert_called_with(b'data4') tr.close() + self.assertFalse(tr.is_reading()) + def pause_writing_transport(self, high): tr = self.socket_transport() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index b1ca3fcf0b1..89c3d5e16c1 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -80,10 +80,23 @@ def test_make_ssl_transport(self): with test_utils.disable_logger(): transport = self.loop._make_ssl_transport( m, asyncio.Protocol(), m, waiter) + + with self.assertRaisesRegex(RuntimeError, + r'SSL transport.*not.*initialized'): + transport.is_reading() + # execute the handshake while the logger is disabled # to ignore SSL handshake failure test_utils.run_briefly(self.loop) + self.assertTrue(transport.is_reading()) + transport.pause_reading() + transport.pause_reading() + self.assertFalse(transport.is_reading()) + transport.resume_reading() + transport.resume_reading() + self.assertTrue(transport.is_reading()) + # Sanity check class_name = transport.__class__.__name__ self.assertIn("ssl", class_name.lower()) @@ -894,15 +907,24 @@ def test_pause_resume_reading(self): tr = self.socket_transport() test_utils.run_briefly(self.loop) self.assertFalse(tr._paused) + self.assertTrue(tr.is_reading()) self.loop.assert_reader(7, tr._read_ready) + + tr.pause_reading() tr.pause_reading() self.assertTrue(tr._paused) - self.assertFalse(7 in self.loop.readers) + self.assertFalse(tr.is_reading()) + self.loop.assert_no_reader(7) + + tr.resume_reading() tr.resume_reading() self.assertFalse(tr._paused) + self.assertTrue(tr.is_reading()) self.loop.assert_reader(7, tr._read_ready) - with self.assertRaises(RuntimeError): - tr.resume_reading() + + tr.close() + self.assertFalse(tr.is_reading()) + self.loop.assert_no_reader(7) def test_read_ready(self): transport = self.socket_transport() diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index a1a9bb3684c..eaafe3af8b8 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -327,12 +327,19 @@ def _remove_reader(self, fd): return False def assert_reader(self, fd, callback, *args): - assert fd in self.readers, 'fd {} is not registered'.format(fd) + if fd not in self.readers: + raise AssertionError(f'fd {fd} is not registered') handle = self.readers[fd] - assert handle._callback == callback, '{!r} != {!r}'.format( - handle._callback, callback) - assert handle._args == args, '{!r} != {!r}'.format( - handle._args, args) + if handle._callback != callback: + raise AssertionError( + f'unexpected callback: {handle._callback} != {callback}') + if handle._args != args: + raise AssertionError( + f'unexpected callback args: {handle._args} != {args}') + + def assert_no_reader(self, fd): + if fd in self.readers: + raise AssertionError(f'fd {fd} is registered') def _add_writer(self, fd, callback, *args): self.writers[fd] = events.Handle(callback, args, self) diff --git a/Misc/NEWS.d/next/Library/2017-12-17-22-50-51.bpo-32356.roZJpA.rst b/Misc/NEWS.d/next/Library/2017-12-17-22-50-51.bpo-32356.roZJpA.rst new file mode 100644 index 00000000000..84b5381fad3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-17-22-50-51.bpo-32356.roZJpA.rst @@ -0,0 +1,2 @@ +asyncio.transport.resume_reading() and pause_reading() are now idempotent. +New transport.is_reading() method is added. From webhook-mailer at python.org Mon Dec 18 17:42:58 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 18 Dec 2017 22:42:58 -0000 Subject: [Python-checkins] bpo-32030: Fix compilation on FreeBSD, #include (#4919) Message-ID: https://github.com/python/cpython/commit/6efcb6d3d5911aaf699f9df3bb3bc26e94f38e6d commit: 6efcb6d3d5911aaf699f9df3bb3bc26e94f38e6d branch: master author: Victor Stinner committer: GitHub date: 2017-12-18T23:42:55+01:00 summary: bpo-32030: Fix compilation on FreeBSD, #include (#4919) * main.c: add missing #include on FreeBSD * indent also other #ifdef in main.c * cleanup Programs/python.c files: M Modules/main.c M Programs/python.c diff --git a/Modules/main.c b/Modules/main.c index 00de7f0d181..4312ef7a1fd 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -9,23 +9,27 @@ #include #if defined(MS_WINDOWS) || defined(__CYGWIN__) -#include -#ifdef HAVE_IO_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif +# include +# ifdef HAVE_IO_H +# include +# endif +# ifdef HAVE_FCNTL_H +# include +# endif #endif #ifdef _MSC_VER -#include +# include +#endif + +#ifdef __FreeBSD__ +# include #endif #if defined(MS_WINDOWS) -#define PYTHONHOMEHELP "\\python{major}{minor}" +# define PYTHONHOMEHELP "\\python{major}{minor}" #else -#define PYTHONHOMEHELP "/lib/pythonX.X" +# define PYTHONHOMEHELP "/lib/pythonX.X" #endif #define COPYRIGHT \ diff --git a/Programs/python.c b/Programs/python.c index a295486d73f..78e48f800c9 100644 --- a/Programs/python.c +++ b/Programs/python.c @@ -1,12 +1,6 @@ /* Minimal main program -- everything is loaded from the library */ #include "Python.h" -#include "internal/pystate.h" -#include - -#ifdef __FreeBSD__ -#include -#endif #ifdef MS_WINDOWS int @@ -15,8 +9,6 @@ wmain(int argc, wchar_t **argv) return Py_Main(argc, argv); } #else - - int main(int argc, char **argv) { From lp_benchmark_robot at intel.com Mon Dec 18 19:43:55 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Mon, 18 Dec 2017 16:43:55 -0800 Subject: [Python-checkins] [1 down, 1 up, 63 flat] Results for Python (master branch) 2017-12-18 Message-ID: Results for project python/master, build date: 2017-12-18 03:03:34-08:00. - commit: b2a6083 - previous commit: 3325a67 - revision date: 2017-12-18 10:28:19+01:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.884% | -0.938% | +5.131% | +8.075% | +-----+------------------------+--------+------------+------------+------------+ | :-( | call_method| 1.171% | -5.141% | +21.376% | +14.801% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.637% | -3.384% | +23.536% | +12.601% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.493% | -3.526% | +20.796% | +12.839% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.963% | +2.292% | +7.654% | +13.364% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.935% | +0.849% | +10.534% | +11.644% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.089% | -0.776% | +5.677% | +11.862% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.468% | -1.243% | -1.795% | +8.621% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 2.226% | -3.373% | +9.527% | +17.850% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.018% | -2.297% | +11.835% | +14.178% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.096% | -0.102% | +4.168% | +6.683% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.367% | +1.248% | +5.751% | +6.196% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.841% | -0.471% | +1.440% | +7.852% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.674% | -1.680% | +11.655% | +11.292% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.423% | +0.003% | +8.815% | +9.068% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.957% | -2.078% | +5.271% | +12.891% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.665% | -0.718% | +10.272% | +11.605% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.249% | +0.624% | +8.733% | +9.113% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.604% | -0.968% | +1.783% | +10.717% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.290% | -0.051% | -0.263% | +14.147% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.475% | +0.096% | +6.949% | +12.633% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.133% | -1.721% | +46.173% | +15.018% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.302% | +0.526% | +8.024% | +14.247% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.458% | +0.224% | +18.187% | +13.014% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 3.168% | +2.646% | +11.331% | +8.441% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 2.118% | -1.216% | +3.607% | +6.399% | +-----+------------------------+--------+------------+------------+------------+ | :-) | nbody| 0.440% | +2.939% | +0.189% | -1.850% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 2.203% | +0.330% | +4.387% | +7.677% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.450% | -1.735% | +4.731% | +11.249% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.487% | -1.506% | +0.053% | +23.140% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.397% | +0.690% | +1.477% | +25.330% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.826% | +1.292% | +3.614% | +21.077% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.750% | -0.357% | +11.148% | +9.824% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.356% | -0.067% | +0.172% | +10.152% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.143% | +0.306% | +10.131% | +4.789% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.135% | +0.313% | +1.313% | +4.671% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.132% | -0.492% | +9.207% | +13.683% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.579% | +2.625% | +4.785% | +10.014% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.304% | +1.538% | -0.879% | +10.417% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.135% | -0.913% | -4.717% | +5.695% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 0.809% | +0.709% | +4.611% | +9.352% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.495% | +0.483% | +8.895% | +14.546% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 1.073% | -0.088% | -3.907% | +3.265% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 2.199% | -0.684% | +26.256% | +8.627% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.650% | -0.258% | +3.377% | +6.738% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.871% | -0.839% | +13.427% | +8.633% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.943% | +2.054% | -3.662% | -0.598% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.505% | +1.191% | +4.890% | +3.212% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.242% | -0.537% | +6.618% | +7.721% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.077% | -0.011% | +6.191% | +4.853% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.877% | +2.093% | +20.873% | +6.834% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 1.791% | +0.419% | +11.826% | +7.553% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.504% | -0.098% | +9.108% | +7.601% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.409% | +0.658% | +11.498% | +7.948% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.006% | +1.598% | +10.830% | +10.158% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.348% | +0.457% | +18.835% | +13.030% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.994% | -0.137% | +5.808% | +7.629% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.067% | -0.187% | +1.891% | +1.505% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.378% | -3.779% | +4.438% | +21.715% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.615% | -3.982% | -5.066% | +16.649% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 0.859% | -0.345% | +7.320% | +7.867% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.458% | -1.583% | +4.103% | +10.633% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 3.695% | +0.492% | +1.865% | +9.472% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 4.075% | -0.279% | -8.199% | +13.687% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.653% | -1.765% | +5.552% | +10.395% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-down-1-up-63-flat-results-for-python-master-branch-2017-12-18 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Mon Dec 18 20:03:01 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 19 Dec 2017 01:03:01 -0000 Subject: [Python-checkins] bpo-32331: Fix socket.type when SOCK_NONBLOCK is available (#4877) Message-ID: https://github.com/python/cpython/commit/9818142b1bd20243733a953fb8aa2c7be314c47c commit: 9818142b1bd20243733a953fb8aa2c7be314c47c branch: master author: Yury Selivanov committer: GitHub date: 2017-12-18T20:02:54-05:00 summary: bpo-32331: Fix socket.type when SOCK_NONBLOCK is available (#4877) files: A Misc/NEWS.d/next/Library/2017-12-15-23-48-43.bpo-32331.fIg1Uc.rst M Doc/library/socket.rst M Doc/whatsnew/3.7.rst M Lib/socket.py M Lib/test/test_asyncore.py M Lib/test/test_socket.py M Modules/socketmodule.c diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 42fd7ea0f0b..db032ca7f1f 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -482,6 +482,20 @@ The following functions all create :ref:`socket objects `. .. versionchanged:: 3.7 The CAN_ISOTP protocol was added. + .. versionchanged:: 3.7 + When :const:`SOCK_NONBLOCK` or :const:`SOCK_CLOEXEC` + bit flags are applied to *type* they are cleared, and + :attr:`socket.type` will not reflect them. They are still passed + to the underlying system `socket()` call. Therefore:: + + sock = socket.socket( + socket.AF_INET, + socket.SOCK_STREAM | socket.SOCK_NONBLOCK) + + will still create a non-blocking socket on OSes that support + ``SOCK_NONBLOCK``, but ``sock.type`` will be set to + ``socket.SOCK_STREAM``. + .. function:: socketpair([family[, type[, proto]]]) Build a pair of connected socket objects using the given address family, socket @@ -1417,6 +1431,10 @@ to sockets. * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0.0)`` + .. versionchanged:: 3.7 + The method no longer applies :const:`SOCK_NONBLOCK` flag on + :attr:`socket.type`. + .. method:: socket.settimeout(value) @@ -1429,6 +1447,10 @@ to sockets. For further information, please consult the :ref:`notes on socket timeouts `. + .. versionchanged:: 3.7 + The method no longer toggles :const:`SOCK_NONBLOCK` flag on + :attr:`socket.type`. + .. method:: socket.setsockopt(level, optname, value: int) .. method:: socket.setsockopt(level, optname, value: buffer) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 82f7cc07043..e5523ff7fd2 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -892,6 +892,13 @@ Changes in the Python API recent to be more consistent with :mod:`traceback`. (Contributed by Jesse Bakker in :issue:`32121`.) +* On OSes that support :const:`socket.SOCK_NONBLOCK` or + :const:`socket.SOCK_CLOEXEC` bit flags, the + :attr:`socket.type ` no longer has them applied. + Therefore, checks like ``if sock.type == socket.SOCK_STREAM`` + work as expected on all platforms. + (Contributed by Yury Selivanov in :issue:`32331`.) + .. _Unicode Technical Standard #18: https://unicode.org/reports/tr18/ * On Windows the default for the *close_fds* argument of diff --git a/Lib/socket.py b/Lib/socket.py index 1ada24d3326..2d8aee3e904 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -203,11 +203,7 @@ def accept(self): For IP sockets, the address info is a pair (hostaddr, port). """ fd, addr = self._accept() - # If our type has the SOCK_NONBLOCK flag, we shouldn't pass it onto the - # new socket. We do not currently allow passing SOCK_NONBLOCK to - # accept4, so the returned socket is always blocking. - type = self.type & ~globals().get("SOCK_NONBLOCK", 0) - sock = socket(self.family, type, self.proto, fileno=fd) + sock = socket(self.family, self.type, self.proto, fileno=fd) # Issue #7995: if no default timeout is set and the listening # socket had a (non-zero) timeout, force the new socket in blocking # mode to override platform-specific socket flags inheritance. diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index ee0c3b371f8..694ddffd687 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -726,14 +726,10 @@ def test_connection_attributes(self): def test_create_socket(self): s = asyncore.dispatcher() s.create_socket(self.family) + self.assertEqual(s.socket.type, socket.SOCK_STREAM) self.assertEqual(s.socket.family, self.family) - SOCK_NONBLOCK = getattr(socket, 'SOCK_NONBLOCK', 0) - sock_type = socket.SOCK_STREAM | SOCK_NONBLOCK - if hasattr(socket, 'SOCK_CLOEXEC'): - self.assertIn(s.socket.type, - (sock_type | socket.SOCK_CLOEXEC, sock_type)) - else: - self.assertEqual(s.socket.type, sock_type) + self.assertEqual(s.socket.gettimeout(), 0) + self.assertFalse(s.socket.get_inheritable()) def test_bind(self): if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 5b4c5f9f8ca..43688eacf06 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1577,6 +1577,22 @@ def test_str_for_enums(self): self.assertEqual(str(s.family), 'AddressFamily.AF_INET') self.assertEqual(str(s.type), 'SocketKind.SOCK_STREAM') + def test_socket_consistent_sock_type(self): + SOCK_NONBLOCK = getattr(socket, 'SOCK_NONBLOCK', 0) + SOCK_CLOEXEC = getattr(socket, 'SOCK_CLOEXEC', 0) + sock_type = socket.SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC + + with socket.socket(socket.AF_INET, sock_type) as s: + self.assertEqual(s.type, socket.SOCK_STREAM) + s.settimeout(1) + self.assertEqual(s.type, socket.SOCK_STREAM) + s.settimeout(0) + self.assertEqual(s.type, socket.SOCK_STREAM) + s.setblocking(True) + self.assertEqual(s.type, socket.SOCK_STREAM) + s.setblocking(False) + self.assertEqual(s.type, socket.SOCK_STREAM) + @unittest.skipIf(os.name == 'nt', 'Will not work on Windows') def test_uknown_socket_family_repr(self): # Test that when created with a family that's not one of the known @@ -1589,9 +1605,18 @@ def test_uknown_socket_family_repr(self): # On Windows this trick won't work, so the test is skipped. fd, path = tempfile.mkstemp() self.addCleanup(os.unlink, path) - with socket.socket(family=42424, type=13331, fileno=fd) as s: - self.assertEqual(s.family, 42424) - self.assertEqual(s.type, 13331) + unknown_family = max(socket.AddressFamily.__members__.values()) + 1 + + unknown_type = max( + kind + for name, kind in socket.SocketKind.__members__.items() + if name not in {'SOCK_NONBLOCK', 'SOCK_CLOEXEC'} + ) + 1 + + with socket.socket( + family=unknown_family, type=unknown_type, fileno=fd) as s: + self.assertEqual(s.family, unknown_family) + self.assertEqual(s.type, unknown_type) @unittest.skipUnless(hasattr(os, 'sendfile'), 'test needs os.sendfile()') def test__sendfile_use_sendfile(self): @@ -5084,7 +5109,7 @@ class InheritanceTest(unittest.TestCase): def test_SOCK_CLOEXEC(self): with socket.socket(socket.AF_INET, socket.SOCK_STREAM | socket.SOCK_CLOEXEC) as s: - self.assertTrue(s.type & socket.SOCK_CLOEXEC) + self.assertEqual(s.type, socket.SOCK_STREAM) self.assertFalse(s.get_inheritable()) def test_default_inheritable(self): @@ -5149,11 +5174,15 @@ def test_socketpair(self): class NonblockConstantTest(unittest.TestCase): def checkNonblock(self, s, nonblock=True, timeout=0.0): if nonblock: - self.assertTrue(s.type & socket.SOCK_NONBLOCK) + self.assertEqual(s.type, socket.SOCK_STREAM) self.assertEqual(s.gettimeout(), timeout) + self.assertTrue( + fcntl.fcntl(s, fcntl.F_GETFL, os.O_NONBLOCK) & os.O_NONBLOCK) else: - self.assertFalse(s.type & socket.SOCK_NONBLOCK) + self.assertEqual(s.type, socket.SOCK_STREAM) self.assertEqual(s.gettimeout(), None) + self.assertFalse( + fcntl.fcntl(s, fcntl.F_GETFL, os.O_NONBLOCK) & os.O_NONBLOCK) @support.requires_linux_version(2, 6, 28) def test_SOCK_NONBLOCK(self): diff --git a/Misc/NEWS.d/next/Library/2017-12-15-23-48-43.bpo-32331.fIg1Uc.rst b/Misc/NEWS.d/next/Library/2017-12-15-23-48-43.bpo-32331.fIg1Uc.rst new file mode 100644 index 00000000000..53a262cf220 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-15-23-48-43.bpo-32331.fIg1Uc.rst @@ -0,0 +1,4 @@ +Fix socket.settimeout() and socket.setblocking() to keep socket.type +as is. Fix socket.socket() constructor to reset any bit flags applied to +socket's type. This change only affects OSes that have SOCK_NONBLOCK +and/or SOCK_CLOEXEC. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 91c879f9d63..d52d9db743a 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -582,12 +582,6 @@ internal_setblocking(PySocketSockObject *s, int block) && !((defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO))) int delay_flag, new_delay_flag; #endif -#ifdef SOCK_NONBLOCK - if (block) - s->sock_type &= (~SOCK_NONBLOCK); - else - s->sock_type |= SOCK_NONBLOCK; -#endif Py_BEGIN_ALLOW_THREADS #ifndef MS_WINDOWS @@ -876,7 +870,22 @@ init_sockobject(PySocketSockObject *s, { s->sock_fd = fd; s->sock_family = family; + s->sock_type = type; + + /* It's possible to pass SOCK_NONBLOCK and SOCK_CLOEXEC bit flags + on some OSes as part of socket.type. We want to reset them here, + to make socket.type be set to the same value on all platforms. + Otherwise, simple code like 'if sock.type == SOCK_STREAM' is + not portable. + */ +#ifdef SOCK_NONBLOCK + s->sock_type = s->sock_type & ~SOCK_NONBLOCK; +#endif +#ifdef SOCK_CLOEXEC + s->sock_type = s->sock_type & ~SOCK_CLOEXEC; +#endif + s->sock_proto = proto; s->errorhandler = &set_error; From webhook-mailer at python.org Tue Dec 19 01:51:18 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Tue, 19 Dec 2017 06:51:18 -0000 Subject: [Python-checkins] Improve test coverage (#4924) Message-ID: https://github.com/python/cpython/commit/21be85f52030b828679ffb9c8cddb5ac48946a30 commit: 21be85f52030b828679ffb9c8cddb5ac48946a30 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-19T08:51:16+02:00 summary: Improve test coverage (#4924) files: M Lib/test/test_asyncio/test_transports.py diff --git a/Lib/test/test_asyncio/test_transports.py b/Lib/test/test_asyncio/test_transports.py index 3b6e3d67075..7de9b3e81a3 100644 --- a/Lib/test/test_asyncio/test_transports.py +++ b/Lib/test/test_asyncio/test_transports.py @@ -42,6 +42,7 @@ def test_not_implemented(self): self.assertRaises(NotImplementedError, transport.can_write_eof) self.assertRaises(NotImplementedError, transport.pause_reading) self.assertRaises(NotImplementedError, transport.resume_reading) + self.assertRaises(NotImplementedError, transport.is_reading) self.assertRaises(NotImplementedError, transport.close) self.assertRaises(NotImplementedError, transport.abort) From webhook-mailer at python.org Tue Dec 19 02:50:51 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 19 Dec 2017 07:50:51 -0000 Subject: [Python-checkins] Allows non-critical upload steps to fail (GH-4742) (#4743) Message-ID: https://github.com/python/cpython/commit/638f68c8bcab46070c73ba31181f484647785d0e commit: 638f68c8bcab46070c73ba31181f484647785d0e branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2017-12-18T23:25:18-05:00 summary: Allows non-critical upload steps to fail (GH-4742) (#4743) (cherry picked from commit 9ab11b3a029fba36c1a7e869be87fb4f31ebcf24) files: M Tools/msi/uploadrelease.proj diff --git a/Tools/msi/uploadrelease.proj b/Tools/msi/uploadrelease.proj index 881b825e107..96b99a4ff63 100644 --- a/Tools/msi/uploadrelease.proj +++ b/Tools/msi/uploadrelease.proj @@ -52,11 +52,11 @@ - + - + - + From webhook-mailer at python.org Tue Dec 19 02:56:34 2017 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 19 Dec 2017 07:56:34 -0000 Subject: [Python-checkins] 3.6.4+ Message-ID: https://github.com/python/cpython/commit/86816ecb98857739ce32acc770b526b6641d5042 commit: 86816ecb98857739ce32acc770b526b6641d5042 branch: 3.6 author: Ned Deily committer: Ned Deily date: 2017-12-19T02:56:06-05:00 summary: 3.6.4+ files: M Include/patchlevel.h diff --git a/Include/patchlevel.h b/Include/patchlevel.h index e909bb240b8..28f3691d886 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.6.4" +#define PY_VERSION "3.6.4+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. From solipsis at pitrou.net Tue Dec 19 04:12:04 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 19 Dec 2017 09:12:04 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-4 Message-ID: <20171219091204.20141.82F7DB215600F913@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 0] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [0, 0, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogmIbVFM', '--timeout', '7200'] From webhook-mailer at python.org Tue Dec 19 05:36:05 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 19 Dec 2017 10:36:05 -0000 Subject: [Python-checkins] bpo-32030: Fix compiler warnings (#4921) Message-ID: https://github.com/python/cpython/commit/5d8624647d0b8ccb22b17b9e819a8e0c3fb4fe4a commit: 5d8624647d0b8ccb22b17b9e819a8e0c3fb4fe4a branch: master author: Victor Stinner committer: GitHub date: 2017-12-19T11:35:58+01:00 summary: bpo-32030: Fix compiler warnings (#4921) Fix compiler warnings in Py_FinalizeEx(): only define variables if they are needed, add #ifdef. Other cleanup changes: * _PyWarnings_InitWithConfig() is no more needed: call _PyWarnings_Init() instead. * Inline pymain_init_main_interpreter() in its caller. This subfunction is no more justifed. files: M Include/warnings.h M Modules/main.c M Python/_warnings.c M Python/pylifecycle.c diff --git a/Include/warnings.h b/Include/warnings.h index 25f715e3a8b..a3f83ff6967 100644 --- a/Include/warnings.h +++ b/Include/warnings.h @@ -7,9 +7,6 @@ extern "C" { #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject*) _PyWarnings_Init(void); #endif -#ifdef Py_BUILD_CORE -PyAPI_FUNC(PyObject*) _PyWarnings_InitWithConfig(const _PyCoreConfig *config); -#endif PyAPI_FUNC(int) PyErr_WarnEx( PyObject *category, diff --git a/Modules/main.c b/Modules/main.c index 4312ef7a1fd..360a0859d4c 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1151,27 +1151,6 @@ pymain_get_program_name(_PyMain *pymain) } -/* Initialize the main interpreter. - * - * Replaces previous call to Py_Initialize() - * - * Return 0 on success. - * Set pymain->err and return -1 on error. - */ -static int -pymain_init_main_interpreter(_PyMain *pymain) -{ - _PyInitError err; - - err = _Py_InitializeMainInterpreter(&pymain->config); - if (_Py_INIT_FAILED(err)) { - pymain->err = err; - return -1; - } - return 0; -} - - static void pymain_header(_PyMain *pymain) { @@ -2357,7 +2336,9 @@ pymain_init_python_main(_PyMain *pymain) return -1; } - if (pymain_init_main_interpreter(pymain)) { + err = _Py_InitializeMainInterpreter(&pymain->config); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; return -1; } diff --git a/Python/_warnings.c b/Python/_warnings.c index 7b2bdd5462c..be8370da06d 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1173,7 +1173,7 @@ create_filter(PyObject *category, _Py_Identifier *id) static PyObject * -init_filters(const _PyCoreConfig *config) +init_filters(void) { #ifdef Py_DEBUG /* Py_DEBUG builds show all warnings by default */ @@ -1218,8 +1218,8 @@ static struct PyModuleDef warningsmodule = { }; -PyObject* -_PyWarnings_InitWithConfig(const _PyCoreConfig *config) +PyMODINIT_FUNC +_PyWarnings_Init(void) { PyObject *m; @@ -1228,7 +1228,7 @@ _PyWarnings_InitWithConfig(const _PyCoreConfig *config) return NULL; if (_PyRuntime.warnings.filters == NULL) { - _PyRuntime.warnings.filters = init_filters(config); + _PyRuntime.warnings.filters = init_filters(); if (_PyRuntime.warnings.filters == NULL) return NULL; } @@ -1259,12 +1259,3 @@ _PyWarnings_InitWithConfig(const _PyCoreConfig *config) _PyRuntime.warnings.filters_version = 0; return m; } - - -PyMODINIT_FUNC -_PyWarnings_Init(void) -{ - PyInterpreterState *interp = PyThreadState_GET()->interp; - const _PyCoreConfig *config = &interp->core_config; - return _PyWarnings_InitWithConfig(config); -} diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 6500995ee24..678fbb63cc8 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -737,7 +737,7 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) } /* Initialize _warnings. */ - if (_PyWarnings_InitWithConfig(&interp->core_config) == NULL) { + if (_PyWarnings_Init() == NULL) { return _Py_INIT_ERR("can't initialize warnings"); } @@ -847,7 +847,9 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) } /* Initialize warnings. */ - if (PySys_HasWarnOptions()) { + if (interp->config.warnoptions != NULL && + PyList_Size(interp->config.warnoptions) > 0) + { PyObject *warnings_module = PyImport_ImportModule("warnings"); if (warnings_module == NULL) { fprintf(stderr, "'import warnings' failed; traceback:\n"); @@ -1021,9 +1023,15 @@ Py_FinalizeEx(void) /* Copy the core config, PyInterpreterState_Delete() free the core config memory */ +#ifdef Py_REF_DEBUG int show_ref_count = interp->core_config.show_ref_count; +#endif +#ifdef Py_TRACE_REFS int dump_refs = interp->core_config.dump_refs; +#endif +#ifdef WITH_PYMALLOC int malloc_stats = interp->core_config.malloc_stats; +#endif /* Remaining threads (e.g. daemon threads) will automatically exit after taking the GIL (in PyEval_RestoreThread()). */ From webhook-mailer at python.org Tue Dec 19 06:44:45 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 19 Dec 2017 11:44:45 -0000 Subject: [Python-checkins] bpo-27456: Simplify sock type checks (#4922) Message-ID: https://github.com/python/cpython/commit/a7bd64c0c01379e9b82e86ad41a301329a0775d9 commit: a7bd64c0c01379e9b82e86ad41a301329a0775d9 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-19T06:44:37-05:00 summary: bpo-27456: Simplify sock type checks (#4922) Recent sock.type fix (see bug 32331) makes sock.type checks simpler in asyncio. files: M Lib/asyncio/base_events.py M Lib/asyncio/selector_events.py M Lib/asyncio/unix_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 398497de09f..bd5bb32302a 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -82,26 +82,6 @@ def _set_reuseport(sock): 'SO_REUSEPORT defined but not implemented.') -def _is_stream_socket(sock_type): - if hasattr(socket, 'SOCK_NONBLOCK'): - # Linux's socket.type is a bitmask that can include extra info - # about socket (like SOCK_NONBLOCK bit), therefore we can't do simple - # `sock_type == socket.SOCK_STREAM`, see - # https://github.com/torvalds/linux/blob/v4.13/include/linux/net.h#L77 - # for more details. - return (sock_type & 0xF) == socket.SOCK_STREAM - else: - return sock_type == socket.SOCK_STREAM - - -def _is_dgram_socket(sock_type): - if hasattr(socket, 'SOCK_NONBLOCK'): - # See the comment in `_is_stream_socket`. - return (sock_type & 0xF) == socket.SOCK_DGRAM - else: - return sock_type == socket.SOCK_DGRAM - - def _ipaddr_info(host, port, family, type, proto): # Try to skip getaddrinfo if "host" is already an IP. Users might have # handled name resolution in their own code and pass in resolved IPs. @@ -112,9 +92,9 @@ def _ipaddr_info(host, port, family, type, proto): host is None: return None - if _is_stream_socket(type): + if type == socket.SOCK_STREAM: proto = socket.IPPROTO_TCP - elif _is_dgram_socket(type): + elif type == socket.SOCK_DGRAM: proto = socket.IPPROTO_UDP else: return None @@ -759,7 +739,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): if sock is None: raise ValueError( 'host and port was not specified and no sock specified') - if not _is_stream_socket(sock.type): + if sock.type != socket.SOCK_STREAM: # We allow AF_INET, AF_INET6, AF_UNIX as long as they # are SOCK_STREAM. # We support passing AF_UNIX sockets even though we have @@ -809,7 +789,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): allow_broadcast=None, sock=None): """Create datagram connection.""" if sock is not None: - if not _is_dgram_socket(sock.type): + if sock.type != socket.SOCK_DGRAM: raise ValueError( f'A UDP Socket was expected, got {sock!r}') if (local_addr or remote_addr or @@ -1037,7 +1017,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): else: if sock is None: raise ValueError('Neither host/port nor sock were specified') - if not _is_stream_socket(sock.type): + if sock.type != socket.SOCK_STREAM: raise ValueError(f'A Stream Socket was expected, got {sock!r}') sockets = [sock] @@ -1060,7 +1040,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): This method is a coroutine. When completed, the coroutine returns a (transport, protocol) pair. """ - if not _is_stream_socket(sock.type): + if sock.type != socket.SOCK_STREAM: raise ValueError(f'A Stream Socket was expected, got {sock!r}') transport, protocol = await self._create_connection_transport( diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 3f44a998b89..3b49b0cb928 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -41,7 +41,7 @@ def _test_selector_event(selector, fd, event): if hasattr(socket, 'TCP_NODELAY'): def _set_nodelay(sock): if (sock.family in {socket.AF_INET, socket.AF_INET6} and - base_events._is_stream_socket(sock.type) and + sock.type == socket.SOCK_STREAM and sock.proto == socket.IPPROTO_TCP): sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) else: diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 50d78c88545..2ab6b154b15 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -222,7 +222,7 @@ def _child_watcher_callback(self, pid, returncode, transp): if sock is None: raise ValueError('no path and sock were specified') if (sock.family != socket.AF_UNIX or - not base_events._is_stream_socket(sock.type)): + sock.type != socket.SOCK_STREAM): raise ValueError( f'A UNIX Domain Stream Socket was expected, got {sock!r}') sock.setblocking(False) @@ -276,7 +276,7 @@ def _child_watcher_callback(self, pid, returncode, transp): 'path was not specified, and no sock specified') if (sock.family != socket.AF_UNIX or - not base_events._is_stream_socket(sock.type)): + sock.type != socket.SOCK_STREAM): raise ValueError( f'A UNIX Domain Stream Socket was expected, got {sock!r}') From webhook-mailer at python.org Tue Dec 19 07:18:48 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 19 Dec 2017 12:18:48 -0000 Subject: [Python-checkins] bpo-32357: Optimize asyncio.iscoroutine() for non-native coroutines (#4915) Message-ID: https://github.com/python/cpython/commit/a9d7e552c72b6e9515e76a1dd4b247da86da23de commit: a9d7e552c72b6e9515e76a1dd4b247da86da23de branch: master author: Yury Selivanov committer: GitHub date: 2017-12-19T07:18:45-05:00 summary: bpo-32357: Optimize asyncio.iscoroutine() for non-native coroutines (#4915) files: A Misc/NEWS.d/next/Library/2017-12-18-00-36-41.bpo-32357.t1F3sn.rst M Lib/asyncio/coroutines.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index e3c0162dd14..9c860a452b5 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -1,5 +1,6 @@ __all__ = 'coroutine', 'iscoroutinefunction', 'iscoroutine' +import collections.abc import functools import inspect import os @@ -7,8 +8,6 @@ import traceback import types -from collections.abc import Awaitable, Coroutine - from . import base_futures from . import constants from . import format_helpers @@ -162,7 +161,7 @@ def coro(*args, **kw): except AttributeError: pass else: - if isinstance(res, Awaitable): + if isinstance(res, collections.abc.Awaitable): res = yield from await_meth() return res @@ -199,12 +198,24 @@ def iscoroutinefunction(func): # Prioritize native coroutine check to speed-up # asyncio.iscoroutine. _COROUTINE_TYPES = (types.CoroutineType, types.GeneratorType, - Coroutine, CoroWrapper) + collections.abc.Coroutine, CoroWrapper) +_iscoroutine_typecache = set() def iscoroutine(obj): """Return True if obj is a coroutine object.""" - return isinstance(obj, _COROUTINE_TYPES) + if type(obj) in _iscoroutine_typecache: + return True + + if isinstance(obj, _COROUTINE_TYPES): + # Just in case we don't want to cache more than 100 + # positive types. That shouldn't ever happen, unless + # someone stressing the system on purpose. + if len(_iscoroutine_typecache) < 100: + _iscoroutine_typecache.add(type(obj)) + return True + else: + return False def _format_coroutine(coro): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 47206613993..f1dbb99d4fc 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -62,6 +62,20 @@ def __call__(self, *args): pass +class CoroLikeObject: + def send(self, v): + raise StopIteration(42) + + def throw(self, *exc): + pass + + def close(self): + pass + + def __await__(self): + return self + + class BaseTaskTests: Task = None @@ -2085,6 +2099,12 @@ def test_create_task_with_noncoroutine(self): "a coroutine was expected, got 123"): self.new_task(self.loop, 123) + # test it for the second time to ensure that caching + # in asyncio.iscoroutine() doesn't break things. + with self.assertRaisesRegex(TypeError, + "a coroutine was expected, got 123"): + self.new_task(self.loop, 123) + def test_create_task_with_oldstyle_coroutine(self): @asyncio.coroutine @@ -2095,6 +2115,12 @@ def coro(): self.assertIsInstance(task, self.Task) self.loop.run_until_complete(task) + # test it for the second time to ensure that caching + # in asyncio.iscoroutine() doesn't break things. + task = self.new_task(self.loop, coro()) + self.assertIsInstance(task, self.Task) + self.loop.run_until_complete(task) + def test_create_task_with_async_function(self): async def coro(): @@ -2104,6 +2130,23 @@ def test_create_task_with_async_function(self): self.assertIsInstance(task, self.Task) self.loop.run_until_complete(task) + # test it for the second time to ensure that caching + # in asyncio.iscoroutine() doesn't break things. + task = self.new_task(self.loop, coro()) + self.assertIsInstance(task, self.Task) + self.loop.run_until_complete(task) + + def test_create_task_with_asynclike_function(self): + task = self.new_task(self.loop, CoroLikeObject()) + self.assertIsInstance(task, self.Task) + self.assertEqual(self.loop.run_until_complete(task), 42) + + # test it for the second time to ensure that caching + # in asyncio.iscoroutine() doesn't break things. + task = self.new_task(self.loop, CoroLikeObject()) + self.assertIsInstance(task, self.Task) + self.assertEqual(self.loop.run_until_complete(task), 42) + def test_bare_create_task(self): async def inner(): diff --git a/Misc/NEWS.d/next/Library/2017-12-18-00-36-41.bpo-32357.t1F3sn.rst b/Misc/NEWS.d/next/Library/2017-12-18-00-36-41.bpo-32357.t1F3sn.rst new file mode 100644 index 00000000000..f51eaf541dc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-18-00-36-41.bpo-32357.t1F3sn.rst @@ -0,0 +1,5 @@ +Optimize asyncio.iscoroutine() and loop.create_task() for non-native +coroutines (e.g. async/await compiled with Cython). + +'loop.create_task(python_coroutine)' used to be 20% faster than +'loop.create_task(cython_coroutine)'. Now, the latter is as fast. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 5030a40b873..33ae067de4b 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -49,6 +49,9 @@ static PyObject *current_tasks; all running event loops. {EventLoop: Task} */ static PyObject *all_tasks; +/* An isinstance type cache for the 'is_coroutine()' function. */ +static PyObject *iscoroutine_typecache; + typedef enum { STATE_PENDING, @@ -118,6 +121,71 @@ static PyObject* future_new_iter(PyObject *); static inline int future_call_schedule_callbacks(FutureObj *); +static int +_is_coroutine(PyObject *coro) +{ + /* 'coro' is not a native coroutine, call asyncio.iscoroutine() + to check if it's another coroutine flavour. + + Do this check after 'future_init()'; in case we need to raise + an error, __del__ needs a properly initialized object. + */ + PyObject *res = PyObject_CallFunctionObjArgs( + asyncio_iscoroutine_func, coro, NULL); + if (res == NULL) { + return -1; + } + + int is_res_true = PyObject_IsTrue(res); + Py_DECREF(res); + if (is_res_true <= 0) { + return is_res_true; + } + + if (PySet_Size(iscoroutine_typecache) < 100) { + /* Just in case we don't want to cache more than 100 + positive types. That shouldn't ever happen, unless + someone stressing the system on purpose. + */ + if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) { + return -1; + } + } + + return 1; +} + + +static inline int +is_coroutine(PyObject *coro) +{ + if (PyCoro_CheckExact(coro)) { + return 1; + } + + /* Check if `type(coro)` is in the cache. + Caching makes is_coroutine() function almost as fast as + PyCoro_CheckExact() for non-native coroutine-like objects + (like coroutines compiled with Cython). + + asyncio.iscoroutine() has its own type caching mechanism. + This cache allows us to avoid the cost of even calling + a pure-Python function in 99.9% cases. + */ + int has_it = PySet_Contains( + iscoroutine_typecache, (PyObject*) Py_TYPE(coro)); + if (has_it == 0) { + /* type(coro) is not in iscoroutine_typecache */ + return _is_coroutine(coro); + } + + /* either an error has occured or + type(coro) is in iscoroutine_typecache + */ + return has_it; +} + + static int get_running_loop(PyObject **loop) { @@ -1778,37 +1846,20 @@ static int _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) /*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/ { - PyObject *res; - if (future_init((FutureObj*)self, loop)) { return -1; } - if (!PyCoro_CheckExact(coro)) { - /* 'coro' is not a native coroutine, call asyncio.iscoroutine() - to check if it's another coroutine flavour. - - Do this check after 'future_init()'; in case we need to raise - an error, __del__ needs a properly initialized object. - */ - res = PyObject_CallFunctionObjArgs( - asyncio_iscoroutine_func, coro, NULL); - if (res == NULL) { - return -1; - } - - int tmp = PyObject_Not(res); - Py_DECREF(res); - if (tmp < 0) { - return -1; - } - if (tmp) { - self->task_log_destroy_pending = 0; - PyErr_Format(PyExc_TypeError, - "a coroutine was expected, got %R", - coro, NULL); - return -1; - } + int is_coro = is_coroutine(coro); + if (is_coro == -1) { + return -1; + } + if (is_coro == 0) { + self->task_log_destroy_pending = 0; + PyErr_Format(PyExc_TypeError, + "a coroutine was expected, got %R", + coro, NULL); + return -1; } self->task_fut_waiter = NULL; @@ -3007,8 +3058,9 @@ module_free(void *m) Py_CLEAR(asyncio_InvalidStateError); Py_CLEAR(asyncio_CancelledError); - Py_CLEAR(current_tasks); Py_CLEAR(all_tasks); + Py_CLEAR(current_tasks); + Py_CLEAR(iscoroutine_typecache); module_free_freelists(); } @@ -3028,6 +3080,11 @@ module_init(void) goto fail; } + iscoroutine_typecache = PySet_New(NULL); + if (iscoroutine_typecache == NULL) { + goto fail; + } + #define WITH_MOD(NAME) \ Py_CLEAR(module); \ module = PyImport_ImportModule(NAME); \ From webhook-mailer at python.org Tue Dec 19 07:19:56 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 19 Dec 2017 12:19:56 -0000 Subject: [Python-checkins] bpo-32355: Optimize asyncio.gather() (#4913) Message-ID: https://github.com/python/cpython/commit/36c2c044782997520df7fc5604742a615ccf6b17 commit: 36c2c044782997520df7fc5604742a615ccf6b17 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-19T07:19:53-05:00 summary: bpo-32355: Optimize asyncio.gather() (#4913) files: A Misc/NEWS.d/next/Library/2017-12-17-21-42-24.bpo-32355.tbaTWA.rst M Lib/asyncio/base_events.py M Lib/asyncio/tasks.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index bd5bb32302a..a7f8edd8cfd 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -139,11 +139,12 @@ def _ipaddr_info(host, port, family, type, proto): def _run_until_complete_cb(fut): - exc = fut._exception - if isinstance(exc, BaseException) and not isinstance(exc, Exception): - # Issue #22429: run_forever() already finished, no need to - # stop it. - return + if not fut.cancelled(): + exc = fut.exception() + if isinstance(exc, BaseException) and not isinstance(exc, Exception): + # Issue #22429: run_forever() already finished, no need to + # stop it. + return fut._loop.stop() diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 275141c65e7..ff8a486b544 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -575,8 +575,7 @@ def cancel(self): def gather(*coros_or_futures, loop=None, return_exceptions=False): - """Return a future aggregating results from the given coroutines - or futures. + """Return a future aggregating results from the given coroutines/futures. Coroutines will be wrapped in a future and scheduled in the event loop. They will not necessarily be scheduled in the same order as @@ -605,56 +604,76 @@ def gather(*coros_or_futures, loop=None, return_exceptions=False): outer.set_result([]) return outer - arg_to_fut = {} - for arg in set(coros_or_futures): - if not futures.isfuture(arg): - fut = ensure_future(arg, loop=loop) - if loop is None: - loop = fut._loop - # The caller cannot control this future, the "destroy pending task" - # warning should not be emitted. - fut._log_destroy_pending = False - else: - fut = arg - if loop is None: - loop = fut._loop - elif fut._loop is not loop: - raise ValueError("futures are tied to different event loops") - arg_to_fut[arg] = fut - - children = [arg_to_fut[arg] for arg in coros_or_futures] - nchildren = len(children) - outer = _GatheringFuture(children, loop=loop) - nfinished = 0 - results = [None] * nchildren - - def _done_callback(i, fut): + def _done_callback(fut): nonlocal nfinished + nfinished += 1 + if outer.done(): if not fut.cancelled(): # Mark exception retrieved. fut.exception() return - if fut.cancelled(): - res = futures.CancelledError() - if not return_exceptions: - outer.set_exception(res) - return - elif fut._exception is not None: - res = fut.exception() # Mark exception retrieved. - if not return_exceptions: - outer.set_exception(res) + if not return_exceptions: + if fut.cancelled(): + # Check if 'fut' is cancelled first, as + # 'fut.exception()' will *raise* a CancelledError + # instead of returning it. + exc = futures.CancelledError() + outer.set_exception(exc) return - else: - res = fut._result - results[i] = res - nfinished += 1 - if nfinished == nchildren: + else: + exc = fut.exception() + if exc is not None: + outer.set_exception(exc) + return + + if nfinished == nfuts: + # All futures are done; create a list of results + # and set it to the 'outer' future. + results = [] + + for fut in children: + if fut.cancelled(): + # Check if 'fut' is cancelled first, as + # 'fut.exception()' will *raise* a CancelledError + # instead of returning it. + res = futures.CancelledError() + else: + res = fut.exception() + if res is None: + res = fut.result() + results.append(res) + outer.set_result(results) - for i, fut in enumerate(children): - fut.add_done_callback(functools.partial(_done_callback, i)) + arg_to_fut = {} + children = [] + nfuts = 0 + nfinished = 0 + for arg in coros_or_futures: + if arg not in arg_to_fut: + fut = ensure_future(arg, loop=loop) + if loop is None: + loop = fut._loop + if fut is not arg: + # 'arg' was not a Future, therefore, 'fut' is a new + # Future created specifically for 'arg'. Since the caller + # can't control it, disable the "destroy pending task" + # warning. + fut._log_destroy_pending = False + + nfuts += 1 + arg_to_fut[arg] = fut + fut.add_done_callback(_done_callback) + + else: + # There's a duplicate Future object in coros_or_futures. + fut = arg_to_fut[arg] + + children.append(fut) + + outer = _GatheringFuture(children, loop=loop) return outer diff --git a/Misc/NEWS.d/next/Library/2017-12-17-21-42-24.bpo-32355.tbaTWA.rst b/Misc/NEWS.d/next/Library/2017-12-17-21-42-24.bpo-32355.tbaTWA.rst new file mode 100644 index 00000000000..ca908e97803 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-17-21-42-24.bpo-32355.tbaTWA.rst @@ -0,0 +1 @@ +Optimize asyncio.gather(); now up to 15% faster. From webhook-mailer at python.org Tue Dec 19 07:23:20 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 19 Dec 2017 12:23:20 -0000 Subject: [Python-checkins] bpo-29711: Fix stop_serving in proactor loop kill all listening servers (#431) Message-ID: https://github.com/python/cpython/commit/319c0345cdd8fddb49d235462e71883f1dd51b99 commit: 319c0345cdd8fddb49d235462e71883f1dd51b99 branch: master author: Julien Duponchelle committer: Yury Selivanov date: 2017-12-19T07:23:17-05:00 summary: bpo-29711: Fix stop_serving in proactor loop kill all listening servers (#431) files: A Misc/NEWS.d/next/Library/2017-12-13-22-10-36.bpo-29711.hJjghA.rst M Lib/asyncio/proactor_events.py M Lib/test/test_asyncio/test_proactor_events.py diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 915ad1ae91c..7044437bbb1 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -536,6 +536,8 @@ def _stop_accept_futures(self): self._accept_futures.clear() def _stop_serving(self, sock): - self._stop_accept_futures() + future = self._accept_futures.pop(sock.fileno(), None) + if future: + future.cancel() self._proactor._stop_serving(sock) sock.close() diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 47ebcad238c..82bff28d7d0 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -567,10 +567,21 @@ def test_create_server_cancel(self): self.assertTrue(self.sock.close.called) def test_stop_serving(self): - sock = mock.Mock() - self.loop._stop_serving(sock) - self.assertTrue(sock.close.called) - self.proactor._stop_serving.assert_called_with(sock) + sock1 = mock.Mock() + future1 = mock.Mock() + sock2 = mock.Mock() + future2 = mock.Mock() + self.loop._accept_futures = { + sock1.fileno(): future1, + sock2.fileno(): future2 + } + + self.loop._stop_serving(sock1) + self.assertTrue(sock1.close.called) + self.assertTrue(future1.cancel.called) + self.proactor._stop_serving.assert_called_with(sock1) + self.assertFalse(sock2.close.called) + self.assertFalse(future2.cancel.called) if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/Library/2017-12-13-22-10-36.bpo-29711.hJjghA.rst b/Misc/NEWS.d/next/Library/2017-12-13-22-10-36.bpo-29711.hJjghA.rst new file mode 100644 index 00000000000..6774172fb6b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-13-22-10-36.bpo-29711.hJjghA.rst @@ -0,0 +1 @@ +Fix ``stop_serving`` in asyncio proactor loop kill all listening servers From webhook-mailer at python.org Tue Dec 19 07:58:53 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 19 Dec 2017 12:58:53 -0000 Subject: [Python-checkins] bpo-26439 Fix ctypes.util.find_library failure on AIX (#4507) Message-ID: https://github.com/python/cpython/commit/c5ae169e1b73315672770517bf51cf8464286c76 commit: c5ae169e1b73315672770517bf51cf8464286c76 branch: master author: Michael Felt committer: Victor Stinner date: 2017-12-19T13:58:49+01:00 summary: bpo-26439 Fix ctypes.util.find_library failure on AIX (#4507) Implement find_library() support in ctypes/util for AIX. Add some AIX specific tests. files: A Lib/ctypes/_aix.py A Misc/NEWS.d/next/Library/2017-11-24-08-35-43.bpo-26439.IC45_f.rst M .gitignore M Lib/ctypes/__init__.py M Lib/ctypes/util.py M Modules/posixmodule.c M configure M configure.ac M pyconfig.h.in diff --git a/.gitignore b/.gitignore index 59206541ee4..05fb6cba087 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ +# added for local development +.buildaix/ +Modules/python.exp +buildaix/ +installp/ +.gitignore + # Two-trick pony for OSX and other case insensitive file systems: # Ignore ./python binary on Unix but still look into ./Python/ directory. /python diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 972ea0ac879..61467739886 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -338,6 +338,14 @@ def __init__(self, name, mode=DEFAULT_MODE, handle=None, flags |= _FUNCFLAG_USE_ERRNO if use_last_error: flags |= _FUNCFLAG_USE_LASTERROR + if _sys.platform.startswith("aix"): + """When the name contains ".a(" and ends with ")", + e.g., "libFOO.a(libFOO.so)" - this is taken to be an + archive(member) syntax for dlopen(), and the mode is adjusted. + Otherwise, name is presented to dlopen() as a file argument. + """ + if name and name.endswith(")") and ".a(" in name: + mode |= ( _os.RTLD_MEMBER | _os.RTLD_NOW ) class _FuncPtr(_CFuncPtr): _flags_ = flags diff --git a/Lib/ctypes/_aix.py b/Lib/ctypes/_aix.py new file mode 100644 index 00000000000..5c4d8d9cc91 --- /dev/null +++ b/Lib/ctypes/_aix.py @@ -0,0 +1,331 @@ +""" +Lib/ctypes.util.find_library() support for AIX +Similar approach as done for Darwin support by using separate files +but unlike Darwin - no extension such as ctypes.macholib.* + +dlopen() is an interface to AIX initAndLoad() - primary documentation at: +https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/dlopen.htm +https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/load.htm + +AIX supports two styles for dlopen(): svr4 (System V Release 4) which is common on posix +platforms, but also a BSD style - aka SVR3. + +From AIX 5.3 Difference Addendum (December 2004) +2.9 SVR4 linking affinity +Nowadays, there are two major object file formats used by the operating systems: +XCOFF: The COFF enhanced by IBM and others. The original COFF (Common +Object File Format) was the base of SVR3 and BSD 4.2 systems. +ELF: Executable and Linking Format that was developed by AT&T and is a +base for SVR4 UNIX. + +While the shared library content is identical on AIX - one is located as a filepath name +(svr4 style) and the other is located as a member of an archive (and the archive +is located as a filepath name). + +The key difference arises when supporting multiple abi formats (i.e., 32 and 64 bit). +For svr4 either only one ABI is supported, or there are two directories, or there +are different file names. The most common solution for multiple ABI is multiple +directories. + +For the XCOFF (aka AIX) style - one directory (one archive file) is sufficient +as multiple shared libraries can be in the archive - even sharing the same name. +In documentation the archive is also referred to as the "base" and the shared +library object is referred to as the "member". + +For dlopen() on AIX (read initAndLoad()) the calls are similiar. +Default activity occurs when no path information is provided. When path +information is provided dlopen() does not search any other directories. + +For SVR4 - the shared library name is the name of the file expected: libFOO.so +For AIX - the shared library is expressed as base(member). The search is for the +base (e.g., libFOO.a) and once the base is found the shared library - identified by +member (e.g., libFOO.so, or shr.o) is located and loaded. + +The mode bit RTLD_MEMBER tells initAndLoad() that it needs to use the AIX (SVR3) +naming style. +""" +__author__ = "Michael Felt " + +import re +from os import environ, path +from sys import executable +from ctypes import c_void_p, sizeof +from subprocess import Popen, PIPE, DEVNULL + +# Executable bit size - 32 or 64 +# Used to filter the search in an archive by size, e.g., -X64 +AIX_ABI = sizeof(c_void_p) * 8 + + +from sys import maxsize +def _last_version(libnames, sep): + def _num_version(libname): + # "libxyz.so.MAJOR.MINOR" => [MAJOR, MINOR] + parts = libname.split(sep) + nums = [] + try: + while parts: + nums.insert(0, int(parts.pop())) + except ValueError: + pass + return nums or [maxsize] + return max(reversed(libnames), key=_num_version) + +def get_ld_header(p): + # "nested-function, but placed at module level + ld_header = None + for line in p.stdout: + if line.startswith(('/', './', '../')): + ld_header = line + elif "INDEX" in line: + return ld_header.rstrip('\n') + return None + +def get_ld_header_info(p): + # "nested-function, but placed at module level + # as an ld_header was found, return known paths, archives and members + # these lines start with a digit + info = [] + for line in p.stdout: + if re.match("[0-9]", line): + info.append(line) + else: + # blank line (seperator), consume line and end for loop + break + return info + +def get_ld_headers(file): + """ + Parse the header of the loader section of executable and archives + This function calls /usr/bin/dump -H as a subprocess + and returns a list of (ld_header, ld_header_info) tuples. + """ + # get_ld_headers parsing: + # 1. Find a line that starts with /, ./, or ../ - set as ld_header + # 2. If "INDEX" in occurs in a following line - return ld_header + # 3. get info (lines starting with [0-9]) + ldr_headers = [] + p = Popen(["/usr/bin/dump", "-X%s" % AIX_ABI, "-H", file], + universal_newlines=True, stdout=PIPE, stderr=DEVNULL) + # be sure to read to the end-of-file - getting all entries + while True: + ld_header = get_ld_header(p) + if ld_header: + ldr_headers.append((ld_header, get_ld_header_info(p))) + else: + break + p.stdout.close() + p.wait + return ldr_headers + +def get_shared(ld_headers): + """ + extract the shareable objects from ld_headers + character "[" is used to strip off the path information. + Note: the "[" and "]" characters that are part of dump -H output + are not removed here. + """ + shared = [] + for (line, _) in ld_headers: + # potential member lines contain "[" + # otherwise, no processing needed + if "[" in line: + # Strip off trailing colon (:) + shared.append(line[line.index("["):-1]) + return shared + +def get_one_match(expr, lines): + """ + Must be only one match, otherwise result is None. + When there is a match, strip leading "[" and trailing "]" + """ + # member names in the ld_headers output are between square brackets + expr = r'\[(%s)\]' % expr + matches = list(filter(None, (re.search(expr, line) for line in lines))) + if len(matches) == 1: + return matches[0].group(1) + else: + return None + +# additional processing to deal with AIX legacy names for 64-bit members +def get_legacy(members): + """ + This routine provides historical aka legacy naming schemes started + in AIX4 shared library support for library members names. + e.g., in /usr/lib/libc.a the member name shr.o for 32-bit binary and + shr_64.o for 64-bit binary. + """ + if AIX_ABI == 64: + # AIX 64-bit member is one of shr64.o, shr_64.o, or shr4_64.o + expr = r'shr4?_?64\.o' + member = get_one_match(expr, members) + if member: + return member + else: + # 32-bit legacy names - both shr.o and shr4.o exist. + # shr.o is the preffered name so we look for shr.o first + # i.e., shr4.o is returned only when shr.o does not exist + for name in ['shr.o', 'shr4.o']: + member = get_one_match(re.escape(name), members) + if member: + return member + return None + +def get_version(name, members): + """ + Sort list of members and return highest numbered version - if it exists. + This function is called when an unversioned libFOO.a(libFOO.so) has + not been found. + + Versioning for the member name is expected to follow + GNU LIBTOOL conventions: the highest version (x, then X.y, then X.Y.z) + * find [libFoo.so.X] + * find [libFoo.so.X.Y] + * find [libFoo.so.X.Y.Z] + + Before the GNU convention became the standard scheme regardless of + binary size AIX packagers used GNU convention "as-is" for 32-bit + archive members but used an "distinguishing" name for 64-bit members. + This scheme inserted either 64 or _64 between libFOO and .so + - generally libFOO_64.so, but occasionally libFOO64.so + """ + # the expression ending for versions must start as + # '.so.[0-9]', i.e., *.so.[at least one digit] + # while multiple, more specific expressions could be specified + # to search for .so.X, .so.X.Y and .so.X.Y.Z + # after the first required 'dot' digit + # any combination of additional 'dot' digits pairs are accepted + # anything more than libFOO.so.digits.digits.digits + # should be seen as a member name outside normal expectations + exprs = [r'lib%s\.so\.[0-9]+[0-9.]*' % name, + r'lib%s_?64\.so\.[0-9]+[0-9.]*' % name] + for expr in exprs: + versions = [] + for line in members: + m = re.search(expr, line) + if m: + versions.append(m.group(0)) + if versions: + return _last_version(versions, '.') + return None + +def get_member(name, members): + """ + Return an archive member matching the request in name. + Name is the library name without any prefix like lib, suffix like .so, + or version number. + Given a list of members find and return the most appropriate result + Priority is given to generic libXXX.so, then a versioned libXXX.so.a.b.c + and finally, legacy AIX naming scheme. + """ + # look first for a generic match - prepend lib and append .so + expr = r'lib%s\.so' % name + member = get_one_match(expr, members) + if member: + return member + elif AIX_ABI == 64: + expr = r'lib%s64\.so' % name + member = get_one_match(expr, members) + if member: + return member + # since an exact match with .so as suffix was not found + # look for a versioned name + # If a versioned name is not found, look for AIX legacy member name + member = get_version(name, members) + if member: + return member + else: + return get_legacy(members) + +def get_libpaths(): + """ + On AIX, the buildtime searchpath is stored in the executable. + as "loader header information". + The command /usr/bin/dump -H extracts this info. + Prefix searched libraries with LD_LIBRARY_PATH (preferred), + or LIBPATH if defined. These paths are appended to the paths + to libraries the python executable is linked with. + This mimics AIX dlopen() behavior. + """ + libpaths = environ.get("LD_LIBRARY_PATH") + if libpaths is None: + libpaths = environ.get("LIBPATH") + if libpaths is None: + libpaths = [] + else: + libpaths = libpaths.split(":") + objects = get_ld_headers(executable) + for (_, lines) in objects: + for line in lines: + # the second (optional) argument is PATH if it includes a / + path = line.split()[1] + if "/" in path: + libpaths.extend(path.split(":")) + return libpaths + +def find_shared(paths, name): + """ + paths is a list of directories to search for an archive. + name is the abbreviated name given to find_library(). + Process: search "paths" for archive, and if an archive is found + return the result of get_member(). + If an archive is not found then return None + """ + for dir in paths: + # /lib is a symbolic link to /usr/lib, skip it + if dir == "/lib": + continue + # "lib" is prefixed to emulate compiler name resolution, + # e.g., -lc to libc + base = 'lib%s.a' % name + archive = path.join(dir, base) + if path.exists(archive): + members = get_shared(get_ld_headers(archive)) + member = get_member(re.escape(name), members) + if member != None: + return (base, member) + else: + return (None, None) + return (None, None) + +def find_library(name): + """AIX implementation of ctypes.util.find_library() + Find an archive member that will dlopen(). If not available, + also search for a file (or link) with a .so suffix. + + AIX supports two types of schemes that can be used with dlopen(). + The so-called SystemV Release4 (svr4) format is commonly suffixed + with .so while the (default) AIX scheme has the library (archive) + ending with the suffix .a + As an archive has multiple members (e.g., 32-bit and 64-bit) in one file + the argument passed to dlopen must include both the library and + the member names in a single string. + + find_library() looks first for an archive (.a) with a suitable member. + If no archive+member pair is found, look for a .so file. + """ + + libpaths = get_libpaths() + (base, member) = find_shared(libpaths, name) + if base != None: + return "%s(%s)" % (base, member) + + # To get here, a member in an archive has not been found + # In other words, either: + # a) a .a file was not found + # b) a .a file did not have a suitable member + # So, look for a .so file + # Check libpaths for .so file + # Note, the installation must prepare a link from a .so + # to a versioned file + # This is common practice by GNU libtool on other platforms + soname = "lib%s.so" % name + for dir in libpaths: + # /lib is a symbolic link to /usr/lib, skip it + if dir == "/lib": + continue + shlib = path.join(dir, soname) + if path.exists(shlib): + return soname + # if we are here, we have not found anything plausible + return None diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 8856f6594c4..e837abba5c8 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -80,6 +80,15 @@ def find_library(name): continue return None +if sys.platform.startswith("aix"): + # AIX has two styles of storing shared libraries + # GNU auto_tools refer to these as svr4 and aix + # svr4 (System V Release 4) is a regular file, often with .so as suffix + # AIX style uses an archive (suffix .a) with members (e.g., shr.o, libssl.so) + # see issue#26439 and _aix.py for more details + + from ctypes._aix import find_library + elif os.name == "posix": # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump import re, tempfile @@ -324,6 +333,22 @@ def test(): print(cdll.LoadLibrary("libcrypto.dylib")) print(cdll.LoadLibrary("libSystem.dylib")) print(cdll.LoadLibrary("System.framework/System")) + # issue-26439 - fix broken test call for AIX + elif sys.platform.startswith("aix"): + from ctypes import CDLL + if sys.maxsize < 2**32: + print("Using CDLL(name, os.RTLD_MEMBER): %s" % CDLL("libc.a(shr.o)", os.RTLD_MEMBER)) + print("Using cdll.LoadLibrary(): %s" % cdll.LoadLibrary("libc.a(shr.o)")) + # librpm.so is only available as 32-bit shared library + print(find_library("rpm")) + print(cdll.LoadLibrary("librpm.so")) + else: + print("Using CDLL(name, os.RTLD_MEMBER): %s" % CDLL("libc.a(shr_64.o)", os.RTLD_MEMBER)) + print("Using cdll.LoadLibrary(): %s" % cdll.LoadLibrary("libc.a(shr_64.o)")) + print("crypt\t:: %s" % find_library("crypt")) + print("crypt\t:: %s" % cdll.LoadLibrary(find_library("crypt"))) + print("crypto\t:: %s" % find_library("crypto")) + print("crypto\t:: %s" % cdll.LoadLibrary(find_library("crypto"))) else: print(cdll.LoadLibrary("libm.so")) print(cdll.LoadLibrary("libcrypt.so")) diff --git a/Misc/NEWS.d/next/Library/2017-11-24-08-35-43.bpo-26439.IC45_f.rst b/Misc/NEWS.d/next/Library/2017-11-24-08-35-43.bpo-26439.IC45_f.rst new file mode 100644 index 00000000000..91c9a45b503 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-24-08-35-43.bpo-26439.IC45_f.rst @@ -0,0 +1,12 @@ +Fix ctypes.util.find_library() for AIX +by implementing ctypes._aix.find_library() +Patch by: Michael Felt aka aixtools + +ctypes.util.find_library has always returned None on a standard AIX. +With this patch there is support for both AIX and svr4 shared libraries. +None is returned only when there is nothinbg found. Normal behavior is now: +on AIX find_library("FOO") returns either libFOO.a(libFOO.so) or libFOO.so +while legacy names e.g., find_library("c") returns libc.a(shr.o) +or libc.a(shr_64.o) - depending on 32 or 64-bit operations. +Include RTLD_MEMBER to mode to support AIX legacy library(member) names +(Modules/_ctype/posixmodule.c), ctypes/__init__.py and configure.ac) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 448d4b7428e..38b6c80e6bd 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -13007,6 +13007,9 @@ all_ins(PyObject *m) #if HAVE_DECL_RTLD_DEEPBIND if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; #endif +#if HAVE_DECL_RTLD_MEMBER + if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1; +#endif #ifdef HAVE_GETRANDOM_SYSCALL if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1; diff --git a/configure b/configure index 20d8095c252..24ae2564091 100755 --- a/configure +++ b/configure @@ -9872,7 +9872,6 @@ fi - if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. @@ -14360,6 +14359,17 @@ fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_RTLD_DEEPBIND $ac_have_decl _ACEOF +ac_fn_c_check_decl "$LINENO" "RTLD_MEMBER" "ac_cv_have_decl_RTLD_MEMBER" "#include +" +if test "x$ac_cv_have_decl_RTLD_MEMBER" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_RTLD_MEMBER $ac_have_decl +_ACEOF # determine what size digit to use for Python's longs diff --git a/configure.ac b/configure.ac index 828dadb56c4..48eaa2ae7f3 100644 --- a/configure.ac +++ b/configure.ac @@ -4480,7 +4480,7 @@ then [define to 1 if your sem_getvalue is broken.]) fi -AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND], [], [], [[#include ]]) +AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, RTLD_MEMBER], [], [], [[#include ]]) # determine what size digit to use for Python's longs AC_MSG_CHECKING([digit size for Python's longs]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 66b9e888274..d828d48af8c 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -210,6 +210,10 @@ don't. */ #undef HAVE_DECL_RTLD_LOCAL +/* Define to 1 if you have the declaration of `RTLD_MEMBER', and to 0 if you + don't. */ +#undef HAVE_DECL_RTLD_MEMBER + /* Define to 1 if you have the declaration of `RTLD_NODELETE', and to 0 if you don't. */ #undef HAVE_DECL_RTLD_NODELETE From webhook-mailer at python.org Tue Dec 19 13:48:17 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 19 Dec 2017 18:48:17 -0000 Subject: [Python-checkins] Fix GCC warning in _asynciomodule.c (#4928) Message-ID: https://github.com/python/cpython/commit/e40ad7965331a3d2d43791f4df71acac9bcb3b1c commit: e40ad7965331a3d2d43791f4df71acac9bcb3b1c branch: master author: Zackery Spytz committer: Yury Selivanov date: 2017-12-19T13:48:13-05:00 summary: Fix GCC warning in _asynciomodule.c (#4928) files: M Modules/_asynciomodule.c diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 33ae067de4b..f52297d33f2 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -3023,7 +3023,7 @@ _asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task) static void -module_free_freelists() +module_free_freelists(void) { PyObject *next; PyObject *current; From webhook-mailer at python.org Tue Dec 19 13:48:48 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Tue, 19 Dec 2017 18:48:48 -0000 Subject: [Python-checkins] bpo-32377: improve __del__ docs and fix mention about resurrection (#4927) Message-ID: https://github.com/python/cpython/commit/4b965930e8625f77cb0e821daf5cc40e85b45f84 commit: 4b965930e8625f77cb0e821daf5cc40e85b45f84 branch: master author: Antoine Pitrou committer: GitHub date: 2017-12-19T19:48:45+01:00 summary: bpo-32377: improve __del__ docs and fix mention about resurrection (#4927) * Fix #32377: improve __del__ docs and fix mention about resurrection * Mention that CPython only calls __del__ once. files: M Doc/glossary.rst M Doc/reference/datamodel.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index e875e1fc8a0..f0fcb6273e0 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -391,7 +391,8 @@ Glossary garbage collection The process of freeing memory when it is not used anymore. Python performs garbage collection via reference counting and a cyclic garbage - collector that is able to detect and break reference cycles. + collector that is able to detect and break reference cycles. The + garbage collector can be controlled using the :mod:`gc` module. .. index:: single: generator diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 790339cd47b..8d47002065f 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1173,61 +1173,69 @@ Basic customization .. index:: single: destructor + single: finalizer statement: del Called when the instance is about to be destroyed. This is also called a - destructor. If a base class has a :meth:`__del__` method, the derived class's - :meth:`__del__` method, if any, must explicitly call it to ensure proper - deletion of the base class part of the instance. Note that it is possible - (though not recommended!) for the :meth:`__del__` method to postpone destruction - of the instance by creating a new reference to it. It may then be called at a - later time when this new reference is deleted. It is not guaranteed that - :meth:`__del__` methods are called for objects that still exist when the - interpreter exits. + finalizer or (improperly) a destructor. If a base class has a + :meth:`__del__` method, the derived class's :meth:`__del__` method, + if any, must explicitly call it to ensure proper deletion of the base + class part of the instance. + + It is possible (though not recommended!) for the :meth:`__del__` method + to postpone destruction of the instance by creating a new reference to + it. This is called object *resurrection*. It is implementation-dependent + whether :meth:`__del__` is called a second time when a resurrected object + is about to be destroyed; the current :term:`CPython` implementation + only calls it once. + + It is not guaranteed that :meth:`__del__` methods are called for objects + that still exist when the interpreter exits. .. note:: ``del x`` doesn't directly call ``x.__del__()`` --- the former decrements the reference count for ``x`` by one, and the latter is only called when - ``x``'s reference count reaches zero. Some common situations that may - prevent the reference count of an object from going to zero include: - circular references between objects (e.g., a doubly-linked list or a tree - data structure with parent and child pointers); a reference to the object - on the stack frame of a function that caught an exception (the traceback - stored in ``sys.exc_info()[2]`` keeps the stack frame alive); or a - reference to the object on the stack frame that raised an unhandled - exception in interactive mode (the traceback stored in - ``sys.last_traceback`` keeps the stack frame alive). The first situation - can only be remedied by explicitly breaking the cycles; the second can be - resolved by freeing the reference to the traceback object when it is no - longer useful, and the third can be resolved by storing ``None`` in - ``sys.last_traceback``. - Circular references which are garbage are detected and cleaned up when - the cyclic garbage collector is enabled (it's on by default). Refer to the - documentation for the :mod:`gc` module for more information about this - topic. + ``x``'s reference count reaches zero. + + .. impl-detail:: + It is possible for a reference cycle to prevent the reference count + of an object from going to zero. In this case, the cycle will be + later detected and deleted by the :term:`cyclic garbage collector + `. A common cause of reference cycles is when + an exception has been caught in a local variable. The frame's + locals then reference the exception, which references its own + traceback, which references the locals of all frames caught in the + traceback. + + .. seealso:: + Documentation for the :mod:`gc` module. .. warning:: Due to the precarious circumstances under which :meth:`__del__` methods are invoked, exceptions that occur during their execution are ignored, and a warning - is printed to ``sys.stderr`` instead. Also, when :meth:`__del__` is invoked in - response to a module being deleted (e.g., when execution of the program is - done), other globals referenced by the :meth:`__del__` method may already have - been deleted or in the process of being torn down (e.g. the import - machinery shutting down). For this reason, :meth:`__del__` methods - should do the absolute - minimum needed to maintain external invariants. Starting with version 1.5, - Python guarantees that globals whose name begins with a single underscore are - deleted from their module before other globals are deleted; if no other - references to such globals exist, this may help in assuring that imported - modules are still available at the time when the :meth:`__del__` method is - called. + is printed to ``sys.stderr`` instead. In particular: - .. index:: - single: repr() (built-in function); __repr__() (object method) + * :meth:`__del__` can be invoked when arbitrary code is being executed, + including from any arbitrary thread. If :meth:`__del__` needs to take + a lock or invoke any other blocking resource, it may deadlock as + the resource may already be taken by the code that gets interrupted + to execute :meth:`__del__`. + + * :meth:`__del__` can be executed during interpreter shutdown. As a + consequence, the global variables it needs to access (including other + modules) may already have been deleted or set to ``None``. Python + guarantees that globals whose name begins with a single underscore + are deleted from their module before other globals are deleted; if + no other references to such globals exist, this may help in assuring + that imported modules are still available at the time when the + :meth:`__del__` method is called. + .. index:: + single: repr() (built-in function); __repr__() (object method) + .. method:: object.__repr__(self) Called by the :func:`repr` built-in function to compute the "official" string From webhook-mailer at python.org Tue Dec 19 14:00:19 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Tue, 19 Dec 2017 19:00:19 -0000 Subject: [Python-checkins] bpo-32377: improve __del__ docs and fix mention about resurrection (GH-4927) (#4929) Message-ID: https://github.com/python/cpython/commit/dc5770b161a5e28eeff73a406cd4eddb0676c5b5 commit: dc5770b161a5e28eeff73a406cd4eddb0676c5b5 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Antoine Pitrou date: 2017-12-19T20:00:13+01:00 summary: bpo-32377: improve __del__ docs and fix mention about resurrection (GH-4927) (#4929) * Fix GH-32377: improve __del__ docs and fix mention about resurrection * Mention that CPython only calls __del__ once. (cherry picked from commit 4b965930e8625f77cb0e821daf5cc40e85b45f84) files: M Doc/glossary.rst M Doc/reference/datamodel.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index b947520b96b..aa5f47ed99a 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -391,7 +391,8 @@ Glossary garbage collection The process of freeing memory when it is not used anymore. Python performs garbage collection via reference counting and a cyclic garbage - collector that is able to detect and break reference cycles. + collector that is able to detect and break reference cycles. The + garbage collector can be controlled using the :mod:`gc` module. .. index:: single: generator diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 230caf843a5..cd11020e0db 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1157,61 +1157,69 @@ Basic customization .. index:: single: destructor + single: finalizer statement: del Called when the instance is about to be destroyed. This is also called a - destructor. If a base class has a :meth:`__del__` method, the derived class's - :meth:`__del__` method, if any, must explicitly call it to ensure proper - deletion of the base class part of the instance. Note that it is possible - (though not recommended!) for the :meth:`__del__` method to postpone destruction - of the instance by creating a new reference to it. It may then be called at a - later time when this new reference is deleted. It is not guaranteed that - :meth:`__del__` methods are called for objects that still exist when the - interpreter exits. + finalizer or (improperly) a destructor. If a base class has a + :meth:`__del__` method, the derived class's :meth:`__del__` method, + if any, must explicitly call it to ensure proper deletion of the base + class part of the instance. + + It is possible (though not recommended!) for the :meth:`__del__` method + to postpone destruction of the instance by creating a new reference to + it. This is called object *resurrection*. It is implementation-dependent + whether :meth:`__del__` is called a second time when a resurrected object + is about to be destroyed; the current :term:`CPython` implementation + only calls it once. + + It is not guaranteed that :meth:`__del__` methods are called for objects + that still exist when the interpreter exits. .. note:: ``del x`` doesn't directly call ``x.__del__()`` --- the former decrements the reference count for ``x`` by one, and the latter is only called when - ``x``'s reference count reaches zero. Some common situations that may - prevent the reference count of an object from going to zero include: - circular references between objects (e.g., a doubly-linked list or a tree - data structure with parent and child pointers); a reference to the object - on the stack frame of a function that caught an exception (the traceback - stored in ``sys.exc_info()[2]`` keeps the stack frame alive); or a - reference to the object on the stack frame that raised an unhandled - exception in interactive mode (the traceback stored in - ``sys.last_traceback`` keeps the stack frame alive). The first situation - can only be remedied by explicitly breaking the cycles; the second can be - resolved by freeing the reference to the traceback object when it is no - longer useful, and the third can be resolved by storing ``None`` in - ``sys.last_traceback``. - Circular references which are garbage are detected and cleaned up when - the cyclic garbage collector is enabled (it's on by default). Refer to the - documentation for the :mod:`gc` module for more information about this - topic. + ``x``'s reference count reaches zero. + + .. impl-detail:: + It is possible for a reference cycle to prevent the reference count + of an object from going to zero. In this case, the cycle will be + later detected and deleted by the :term:`cyclic garbage collector + `. A common cause of reference cycles is when + an exception has been caught in a local variable. The frame's + locals then reference the exception, which references its own + traceback, which references the locals of all frames caught in the + traceback. + + .. seealso:: + Documentation for the :mod:`gc` module. .. warning:: Due to the precarious circumstances under which :meth:`__del__` methods are invoked, exceptions that occur during their execution are ignored, and a warning - is printed to ``sys.stderr`` instead. Also, when :meth:`__del__` is invoked in - response to a module being deleted (e.g., when execution of the program is - done), other globals referenced by the :meth:`__del__` method may already have - been deleted or in the process of being torn down (e.g. the import - machinery shutting down). For this reason, :meth:`__del__` methods - should do the absolute - minimum needed to maintain external invariants. Starting with version 1.5, - Python guarantees that globals whose name begins with a single underscore are - deleted from their module before other globals are deleted; if no other - references to such globals exist, this may help in assuring that imported - modules are still available at the time when the :meth:`__del__` method is - called. + is printed to ``sys.stderr`` instead. In particular: - .. index:: - single: repr() (built-in function); __repr__() (object method) + * :meth:`__del__` can be invoked when arbitrary code is being executed, + including from any arbitrary thread. If :meth:`__del__` needs to take + a lock or invoke any other blocking resource, it may deadlock as + the resource may already be taken by the code that gets interrupted + to execute :meth:`__del__`. + + * :meth:`__del__` can be executed during interpreter shutdown. As a + consequence, the global variables it needs to access (including other + modules) may already have been deleted or set to ``None``. Python + guarantees that globals whose name begins with a single underscore + are deleted from their module before other globals are deleted; if + no other references to such globals exist, this may help in assuring + that imported modules are still available at the time when the + :meth:`__del__` method is called. + .. index:: + single: repr() (built-in function); __repr__() (object method) + .. method:: object.__repr__(self) Called by the :func:`repr` built-in function to compute the "official" string From webhook-mailer at python.org Tue Dec 19 14:45:45 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Tue, 19 Dec 2017 19:45:45 -0000 Subject: [Python-checkins] bpo-29970: Add timeout for SSL handshake in asyncio Message-ID: https://github.com/python/cpython/commit/f7686c1f5553b24e3307506a18e18f6544de94d3 commit: f7686c1f5553b24e3307506a18e18f6544de94d3 branch: master author: Neil Aspinall committer: Andrew Svetlov date: 2017-12-19T21:45:42+02:00 summary: bpo-29970: Add timeout for SSL handshake in asyncio 10 seconds by default. files: A Misc/NEWS.d/next/Library/2017-12-13-19-02-38.bpo-29970.uxVOpk.rst M Doc/library/asyncio-eventloop.rst M Lib/asyncio/base_events.py M Lib/asyncio/constants.py M Lib/asyncio/events.py M Lib/asyncio/proactor_events.py M Lib/asyncio/selector_events.py M Lib/asyncio/sslproto.py M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_sslproto.py M Misc/ACKS diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 26798783fe7..d20e995d353 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -261,7 +261,7 @@ Tasks Creating connections -------------------- -.. coroutinemethod:: AbstractEventLoop.create_connection(protocol_factory, host=None, port=None, \*, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None) +.. coroutinemethod:: AbstractEventLoop.create_connection(protocol_factory, host=None, port=None, \*, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=10.0) Create a streaming transport connection to a given Internet *host* and *port*: socket family :py:data:`~socket.AF_INET` or @@ -325,6 +325,13 @@ Creating connections to bind the socket to locally. The *local_host* and *local_port* are looked up using getaddrinfo(), similarly to *host* and *port*. + * *ssl_handshake_timeout* is (for an SSL connection) the time in seconds + to wait for the SSL handshake to complete before aborting the connection. + + .. versionadded:: 3.7 + + The *ssl_handshake_timeout* parameter. + .. versionchanged:: 3.5 On Windows with :class:`ProactorEventLoop`, SSL/TLS is now supported. @@ -386,7 +393,7 @@ Creating connections :ref:`UDP echo server protocol ` examples. -.. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path=None, \*, ssl=None, sock=None, server_hostname=None) +.. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path=None, \*, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=10.0) Create UNIX connection: socket family :py:data:`~socket.AF_UNIX`, socket type :py:data:`~socket.SOCK_STREAM`. The :py:data:`~socket.AF_UNIX` socket @@ -404,6 +411,10 @@ Creating connections Availability: UNIX. + .. versionadded:: 3.7 + + The *ssl_handshake_timeout* parameter. + .. versionchanged:: 3.7 The *path* parameter can now be a :class:`~pathlib.Path` object. @@ -412,7 +423,7 @@ Creating connections Creating listening connections ------------------------------ -.. coroutinemethod:: AbstractEventLoop.create_server(protocol_factory, host=None, port=None, \*, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None) +.. coroutinemethod:: AbstractEventLoop.create_server(protocol_factory, host=None, port=None, \*, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=10.0) Create a TCP server (socket type :data:`~socket.SOCK_STREAM`) bound to *host* and *port*. @@ -456,6 +467,13 @@ Creating listening connections set this flag when being created. This option is not supported on Windows. + * *ssl_handshake_timeout* is (for an SSL server) the time in seconds to wait + for the SSL handshake to complete before aborting the connection. + + .. versionadded:: 3.7 + + The *ssl_handshake_timeout* parameter. + .. versionchanged:: 3.5 On Windows with :class:`ProactorEventLoop`, SSL/TLS is now supported. @@ -470,7 +488,7 @@ Creating listening connections The *host* parameter can now be a sequence of strings. -.. coroutinemethod:: AbstractEventLoop.create_unix_server(protocol_factory, path=None, \*, sock=None, backlog=100, ssl=None) +.. coroutinemethod:: AbstractEventLoop.create_unix_server(protocol_factory, path=None, \*, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=10.0) Similar to :meth:`AbstractEventLoop.create_server`, but specific to the socket family :py:data:`~socket.AF_UNIX`. @@ -481,11 +499,15 @@ Creating listening connections Availability: UNIX. + .. versionadded:: 3.7 + + The *ssl_handshake_timeout* parameter. + .. versionchanged:: 3.7 The *path* parameter can now be a :class:`~pathlib.Path` object. -.. coroutinemethod:: BaseEventLoop.connect_accepted_socket(protocol_factory, sock, \*, ssl=None) +.. coroutinemethod:: BaseEventLoop.connect_accepted_socket(protocol_factory, sock, \*, ssl=None, ssl_handshake_timeout=10.0) Handle an accepted connection. @@ -500,8 +522,15 @@ Creating listening connections * *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over the accepted connections. + * *ssl_handshake_timeout* is (for an SSL connection) the time in seconds to + wait for the SSL handshake to complete before aborting the connection. + When completed it returns a ``(transport, protocol)`` pair. + .. versionadded:: 3.7 + + The *ssl_handshake_timeout* parameter. + .. versionadded:: 3.5.3 diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index a7f8edd8cfd..6246f4e221c 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -29,6 +29,7 @@ import warnings import weakref +from . import constants from . import coroutines from . import events from . import futures @@ -275,9 +276,11 @@ def _make_socket_transport(self, sock, protocol, waiter=None, *, """Create socket transport.""" raise NotImplementedError - def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None, - *, server_side=False, server_hostname=None, - extra=None, server=None): + def _make_ssl_transport( + self, rawsock, protocol, sslcontext, waiter=None, + *, server_side=False, server_hostname=None, + extra=None, server=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): """Create SSL transport.""" raise NotImplementedError @@ -635,10 +638,12 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): return await self.run_in_executor( None, socket.getnameinfo, sockaddr, flags) - async def create_connection(self, protocol_factory, host=None, port=None, - *, ssl=None, family=0, - proto=0, flags=0, sock=None, - local_addr=None, server_hostname=None): + async def create_connection( + self, protocol_factory, host=None, port=None, + *, ssl=None, family=0, + proto=0, flags=0, sock=None, + local_addr=None, server_hostname=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): """Connect to a TCP server. Create a streaming transport connection to a given Internet host and @@ -751,7 +756,8 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): f'A Stream Socket was expected, got {sock!r}') transport, protocol = await self._create_connection_transport( - sock, protocol_factory, ssl, server_hostname) + sock, protocol_factory, ssl, server_hostname, + ssl_handshake_timeout=ssl_handshake_timeout) if self._debug: # Get the socket from the transport because SSL transport closes # the old socket and creates a new SSL socket @@ -760,8 +766,10 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): sock, host, port, transport, protocol) return transport, protocol - async def _create_connection_transport(self, sock, protocol_factory, ssl, - server_hostname, server_side=False): + async def _create_connection_transport( + self, sock, protocol_factory, ssl, + server_hostname, server_side=False, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): sock.setblocking(False) @@ -771,7 +779,8 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): sslcontext = None if isinstance(ssl, bool) else ssl transport = self._make_ssl_transport( sock, protocol, sslcontext, waiter, - server_side=server_side, server_hostname=server_hostname) + server_side=server_side, server_hostname=server_hostname, + ssl_handshake_timeout=ssl_handshake_timeout) else: transport = self._make_socket_transport(sock, protocol, waiter) @@ -929,15 +938,17 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): raise OSError(f'getaddrinfo({host!r}) returned empty list') return infos - async def create_server(self, protocol_factory, host=None, port=None, - *, - family=socket.AF_UNSPEC, - flags=socket.AI_PASSIVE, - sock=None, - backlog=100, - ssl=None, - reuse_address=None, - reuse_port=None): + async def create_server( + self, protocol_factory, host=None, port=None, + *, + family=socket.AF_UNSPEC, + flags=socket.AI_PASSIVE, + sock=None, + backlog=100, + ssl=None, + reuse_address=None, + reuse_port=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): """Create a TCP server. The host parameter can be a string, in that case the TCP server is @@ -1026,13 +1037,16 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): for sock in sockets: sock.listen(backlog) sock.setblocking(False) - self._start_serving(protocol_factory, sock, ssl, server, backlog) + self._start_serving(protocol_factory, sock, ssl, server, backlog, + ssl_handshake_timeout) if self._debug: logger.info("%r is serving", server) return server - async def connect_accepted_socket(self, protocol_factory, sock, - *, ssl=None): + async def connect_accepted_socket( + self, protocol_factory, sock, + *, ssl=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): """Handle an accepted connection. This is used by servers that accept connections outside of @@ -1045,7 +1059,8 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): raise ValueError(f'A Stream Socket was expected, got {sock!r}') transport, protocol = await self._create_connection_transport( - sock, protocol_factory, ssl, '', server_side=True) + sock, protocol_factory, ssl, '', server_side=True, + ssl_handshake_timeout=ssl_handshake_timeout) if self._debug: # Get the socket from the transport because SSL transport closes # the old socket and creates a new SSL socket diff --git a/Lib/asyncio/constants.py b/Lib/asyncio/constants.py index 52169c3f8e5..0ad974ff2fb 100644 --- a/Lib/asyncio/constants.py +++ b/Lib/asyncio/constants.py @@ -8,3 +8,6 @@ # The larger the number, the slower the operation in debug mode # (see extract_stack() in format_helpers.py). DEBUG_STACK_DEPTH = 10 + +# Number of seconds to wait for SSL handshake to complete +SSL_HANDSHAKE_TIMEOUT = 10.0 diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 974a4a22218..c9033c020f3 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -250,16 +250,20 @@ def set_default_executor(self, executor): async def getnameinfo(self, sockaddr, flags=0): raise NotImplementedError - async def create_connection(self, protocol_factory, host=None, port=None, - *, ssl=None, family=0, proto=0, - flags=0, sock=None, local_addr=None, - server_hostname=None): - raise NotImplementedError - - async def create_server(self, protocol_factory, host=None, port=None, - *, family=socket.AF_UNSPEC, - flags=socket.AI_PASSIVE, sock=None, backlog=100, - ssl=None, reuse_address=None, reuse_port=None): + async def create_connection( + self, protocol_factory, host=None, port=None, + *, ssl=None, family=0, proto=0, + flags=0, sock=None, local_addr=None, + server_hostname=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + raise NotImplementedError + + async def create_server( + self, protocol_factory, host=None, port=None, + *, family=socket.AF_UNSPEC, + flags=socket.AI_PASSIVE, sock=None, backlog=100, + ssl=None, reuse_address=None, reuse_port=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): """A coroutine which creates a TCP server bound to host and port. The return value is a Server object which can be used to stop @@ -294,16 +298,25 @@ def set_default_executor(self, executor): the same port as other existing endpoints are bound to, so long as they all set this flag when being created. This option is not supported on Windows. + + ssl_handshake_timeout is the time in seconds that an SSL server + will wait for completion of the SSL handshake before aborting the + connection. Default is 10s, longer timeouts may increase vulnerability + to DoS attacks (see https://support.f5.com/csp/article/K13834) """ raise NotImplementedError - async def create_unix_connection(self, protocol_factory, path=None, *, - ssl=None, sock=None, - server_hostname=None): + async def create_unix_connection( + self, protocol_factory, path=None, *, + ssl=None, sock=None, + server_hostname=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): raise NotImplementedError - async def create_unix_server(self, protocol_factory, path=None, *, - sock=None, backlog=100, ssl=None): + async def create_unix_server( + self, protocol_factory, path=None, *, + sock=None, backlog=100, ssl=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): """A coroutine which creates a UNIX Domain Socket server. The return value is a Server object, which can be used to stop @@ -320,6 +333,9 @@ def set_default_executor(self, executor): ssl can be set to an SSLContext to enable SSL over the accepted connections. + + ssl_handshake_timeout is the time in seconds that an SSL server + will wait for the SSL handshake to complete (defaults to 10s). """ raise NotImplementedError diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 7044437bbb1..bc319b06ed6 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -389,11 +389,15 @@ def _make_socket_transport(self, sock, protocol, waiter=None, return _ProactorSocketTransport(self, sock, protocol, waiter, extra, server) - def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None, - *, server_side=False, server_hostname=None, - extra=None, server=None): - ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter, - server_side, server_hostname) + def _make_ssl_transport( + self, rawsock, protocol, sslcontext, waiter=None, + *, server_side=False, server_hostname=None, + extra=None, server=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_protocol = sslproto.SSLProtocol( + self, protocol, sslcontext, waiter, + server_side, server_hostname, + ssl_handshake_timeout=ssl_handshake_timeout) _ProactorSocketTransport(self, rawsock, ssl_protocol, extra=extra, server=server) return ssl_protocol._app_transport @@ -486,7 +490,8 @@ def _write_to_self(self): self._csock.send(b'\0') def _start_serving(self, protocol_factory, sock, - sslcontext=None, server=None, backlog=100): + sslcontext=None, server=None, backlog=100, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): def loop(f=None): try: @@ -499,7 +504,8 @@ def loop(f=None): if sslcontext is not None: self._make_ssl_transport( conn, protocol, sslcontext, server_side=True, - extra={'peername': addr}, server=server) + extra={'peername': addr}, server=server, + ssl_handshake_timeout=ssl_handshake_timeout) else: self._make_socket_transport( conn, protocol, diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 3b49b0cb928..1e4bd83a1b1 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -70,11 +70,15 @@ def _make_socket_transport(self, sock, protocol, waiter=None, *, return _SelectorSocketTransport(self, sock, protocol, waiter, extra, server) - def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None, - *, server_side=False, server_hostname=None, - extra=None, server=None): - ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter, - server_side, server_hostname) + def _make_ssl_transport( + self, rawsock, protocol, sslcontext, waiter=None, + *, server_side=False, server_hostname=None, + extra=None, server=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_protocol = sslproto.SSLProtocol( + self, protocol, sslcontext, waiter, + server_side, server_hostname, + ssl_handshake_timeout=ssl_handshake_timeout) _SelectorSocketTransport(self, rawsock, ssl_protocol, extra=extra, server=server) return ssl_protocol._app_transport @@ -143,12 +147,16 @@ def _write_to_self(self): exc_info=True) def _start_serving(self, protocol_factory, sock, - sslcontext=None, server=None, backlog=100): + sslcontext=None, server=None, backlog=100, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): self._add_reader(sock.fileno(), self._accept_connection, - protocol_factory, sock, sslcontext, server, backlog) + protocol_factory, sock, sslcontext, server, backlog, + ssl_handshake_timeout) - def _accept_connection(self, protocol_factory, sock, - sslcontext=None, server=None, backlog=100): + def _accept_connection( + self, protocol_factory, sock, + sslcontext=None, server=None, backlog=100, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): # This method is only called once for each event loop tick where the # listening socket has triggered an EVENT_READ. There may be multiple # connections waiting for an .accept() so it is called in a loop. @@ -179,17 +187,20 @@ def _accept_connection(self, protocol_factory, sock, self.call_later(constants.ACCEPT_RETRY_DELAY, self._start_serving, protocol_factory, sock, sslcontext, server, - backlog) + backlog, ssl_handshake_timeout) else: raise # The event loop will catch, log and ignore it. else: extra = {'peername': addr} accept = self._accept_connection2( - protocol_factory, conn, extra, sslcontext, server) + protocol_factory, conn, extra, sslcontext, server, + ssl_handshake_timeout) self.create_task(accept) - async def _accept_connection2(self, protocol_factory, conn, extra, - sslcontext=None, server=None): + async def _accept_connection2( + self, protocol_factory, conn, extra, + sslcontext=None, server=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): protocol = None transport = None try: @@ -198,7 +209,8 @@ def _accept_connection(self, protocol_factory, sock, if sslcontext: transport = self._make_ssl_transport( conn, protocol, sslcontext, waiter=waiter, - server_side=True, extra=extra, server=server) + server_side=True, extra=extra, server=server, + ssl_handshake_timeout=ssl_handshake_timeout) else: transport = self._make_socket_transport( conn, protocol, waiter=waiter, extra=extra, diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 8da8570d66d..8bcc6cc0433 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -6,6 +6,7 @@ ssl = None from . import base_events +from . import constants from . import protocols from . import transports from .log import logger @@ -400,7 +401,8 @@ class SSLProtocol(protocols.Protocol): def __init__(self, loop, app_protocol, sslcontext, waiter, server_side=False, server_hostname=None, - call_connection_made=True): + call_connection_made=True, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): if ssl is None: raise RuntimeError('stdlib ssl module not available') @@ -434,6 +436,7 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, # transport, ex: SelectorSocketTransport self._transport = None self._call_connection_made = call_connection_made + self._ssl_handshake_timeout = ssl_handshake_timeout def _wakeup_waiter(self, exc=None): if self._waiter is None: @@ -561,9 +564,18 @@ def _start_handshake(self): # the SSL handshake self._write_backlog.append((b'', 1)) self._loop.call_soon(self._process_write_backlog) + self._handshake_timeout_handle = \ + self._loop.call_later(self._ssl_handshake_timeout, + self._check_handshake_timeout) + + def _check_handshake_timeout(self): + if self._in_handshake is True: + logger.warning("%r stalled during handshake", self) + self._abort() def _on_handshake_complete(self, handshake_exc): self._in_handshake = False + self._handshake_timeout_handle.cancel() sslobj = self._sslpipe.ssl_object try: diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 2ab6b154b15..e2344582268 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -192,9 +192,11 @@ def _make_write_pipe_transport(self, pipe, protocol, waiter=None, def _child_watcher_callback(self, pid, returncode, transp): self.call_soon_threadsafe(transp._process_exited, returncode) - async def create_unix_connection(self, protocol_factory, path=None, *, - ssl=None, sock=None, - server_hostname=None): + async def create_unix_connection( + self, protocol_factory, path=None, *, + ssl=None, sock=None, + server_hostname=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): assert server_hostname is None or isinstance(server_hostname, str) if ssl: if server_hostname is None: @@ -228,11 +230,14 @@ def _child_watcher_callback(self, pid, returncode, transp): sock.setblocking(False) transport, protocol = await self._create_connection_transport( - sock, protocol_factory, ssl, server_hostname) + sock, protocol_factory, ssl, server_hostname, + ssl_handshake_timeout=ssl_handshake_timeout) return transport, protocol - async def create_unix_server(self, protocol_factory, path=None, *, - sock=None, backlog=100, ssl=None): + async def create_unix_server( + self, protocol_factory, path=None, *, + sock=None, backlog=100, ssl=None, + ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): if isinstance(ssl, bool): raise TypeError('ssl argument must be an SSLContext or None') @@ -283,7 +288,8 @@ def _child_watcher_callback(self, pid, returncode, transp): server = base_events.Server(self, [sock]) sock.listen(backlog) sock.setblocking(False) - self._start_serving(protocol_factory, sock, ssl, server) + self._start_serving(protocol_factory, sock, ssl, server, + ssl_handshake_timeout=ssl_handshake_timeout) return server diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 1d45cf86425..488257b341f 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1301,34 +1301,45 @@ def mock_make_ssl_transport(sock, protocol, sslcontext, waiter, self.loop._make_ssl_transport.side_effect = mock_make_ssl_transport ANY = mock.ANY + handshake_timeout = object() # First try the default server_hostname. self.loop._make_ssl_transport.reset_mock() - coro = self.loop.create_connection(MyProto, 'python.org', 80, ssl=True) + coro = self.loop.create_connection( + MyProto, 'python.org', 80, ssl=True, + ssl_handshake_timeout=handshake_timeout) transport, _ = self.loop.run_until_complete(coro) transport.close() self.loop._make_ssl_transport.assert_called_with( ANY, ANY, ANY, ANY, server_side=False, - server_hostname='python.org') + server_hostname='python.org', + ssl_handshake_timeout=handshake_timeout) # Next try an explicit server_hostname. self.loop._make_ssl_transport.reset_mock() - coro = self.loop.create_connection(MyProto, 'python.org', 80, ssl=True, - server_hostname='perl.com') + coro = self.loop.create_connection( + MyProto, 'python.org', 80, ssl=True, + server_hostname='perl.com', + ssl_handshake_timeout=handshake_timeout) transport, _ = self.loop.run_until_complete(coro) transport.close() self.loop._make_ssl_transport.assert_called_with( ANY, ANY, ANY, ANY, server_side=False, - server_hostname='perl.com') + server_hostname='perl.com', + ssl_handshake_timeout=handshake_timeout) # Finally try an explicit empty server_hostname. self.loop._make_ssl_transport.reset_mock() - coro = self.loop.create_connection(MyProto, 'python.org', 80, ssl=True, - server_hostname='') + coro = self.loop.create_connection( + MyProto, 'python.org', 80, ssl=True, + server_hostname='', + ssl_handshake_timeout=handshake_timeout) transport, _ = self.loop.run_until_complete(coro) transport.close() - self.loop._make_ssl_transport.assert_called_with(ANY, ANY, ANY, ANY, - server_side=False, - server_hostname='') + self.loop._make_ssl_transport.assert_called_with( + ANY, ANY, ANY, ANY, + server_side=False, + server_hostname='', + ssl_handshake_timeout=handshake_timeout) def test_create_connection_no_ssl_server_hostname_errors(self): # When not using ssl, server_hostname must be None. @@ -1687,7 +1698,7 @@ def test_accept_connection_exception(self, m_log): constants.ACCEPT_RETRY_DELAY, # self.loop._start_serving mock.ANY, - MyProto, sock, None, None, mock.ANY) + MyProto, sock, None, None, mock.ANY, mock.ANY) def test_call_coroutine(self): @asyncio.coroutine diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 7650fe6bd46..1c42a35128f 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -11,6 +11,7 @@ import asyncio from asyncio import log from asyncio import sslproto +from asyncio import tasks from test.test_asyncio import utils as test_utils @@ -25,7 +26,8 @@ def setUp(self): def ssl_protocol(self, waiter=None): sslcontext = test_utils.dummy_ssl_context() app_proto = asyncio.Protocol() - proto = sslproto.SSLProtocol(self.loop, app_proto, sslcontext, waiter) + proto = sslproto.SSLProtocol(self.loop, app_proto, sslcontext, waiter, + ssl_handshake_timeout=0.1) self.assertIs(proto._app_transport.get_protocol(), app_proto) self.addCleanup(proto._app_transport.close) return proto @@ -63,6 +65,16 @@ def do_handshake(callback): with test_utils.disable_logger(): self.loop.run_until_complete(handshake_fut) + def test_handshake_timeout(self): + # bpo-29970: Check that a connection is aborted if handshake is not + # completed in timeout period, instead of remaining open indefinitely + ssl_proto = self.ssl_protocol() + transport = self.connection_made(ssl_proto) + + with test_utils.disable_logger(): + self.loop.run_until_complete(tasks.sleep(0.2, loop=self.loop)) + self.assertTrue(transport.abort.called) + def test_eof_received_waiter(self): waiter = asyncio.Future(loop=self.loop) ssl_proto = self.ssl_protocol(waiter) diff --git a/Misc/ACKS b/Misc/ACKS index e5343899640..009b072d680 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -63,6 +63,7 @@ Jeffrey Armstrong Jason Asbahr David Ascher Ammar Askar +Neil Aspinall Chris AtLee Aymeric Augustin Cathy Avery diff --git a/Misc/NEWS.d/next/Library/2017-12-13-19-02-38.bpo-29970.uxVOpk.rst b/Misc/NEWS.d/next/Library/2017-12-13-19-02-38.bpo-29970.uxVOpk.rst new file mode 100644 index 00000000000..d3d9ae94b32 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-13-19-02-38.bpo-29970.uxVOpk.rst @@ -0,0 +1 @@ +Abort asyncio SSLProtocol connection if handshake not complete within 10s From webhook-mailer at python.org Tue Dec 19 16:03:13 2017 From: webhook-mailer at python.org (Mariatta) Date: Tue, 19 Dec 2017 21:03:13 -0000 Subject: [Python-checkins] Improve the F-strings and format specifier documentation (GH-4931) Message-ID: https://github.com/python/cpython/commit/f4e21a2a72f76d75a6cc6f74faf910a5f3108482 commit: f4e21a2a72f76d75a6cc6f74faf910a5f3108482 branch: master author: KatherineMichel committer: Mariatta date: 2017-12-19T13:03:09-08:00 summary: Improve the F-strings and format specifier documentation (GH-4931) Mention that the format-specifier mini language in f-strings is the same one used by str.format. files: M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 86e55e4d9c8..0f9cb684c68 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -654,10 +654,11 @@ expression or conversion result. An empty string is passed when the format specifier is omitted. The formatted result is then included in the final value of the whole string. -Top-level format specifiers may include nested replacement fields. -These nested fields may include their own conversion fields and -:ref:`format specifiers `, but may not include more -deeply-nested replacement fields. +Top-level format specifiers may include nested replacement fields. These nested +fields may include their own conversion fields and :ref:`format specifiers +`, but may not include more deeply-nested replacement fields. The +:ref:`format specifier mini-language ` is the same as that used by +the string .format() method. Formatted string literals may be concatenated, but replacement fields cannot be split across literals. From webhook-mailer at python.org Tue Dec 19 16:09:21 2017 From: webhook-mailer at python.org (Mariatta) Date: Tue, 19 Dec 2017 21:09:21 -0000 Subject: [Python-checkins] Improve the F-strings and format specifier documentation (GH-4931) (GH-4933) Message-ID: https://github.com/python/cpython/commit/75d1ca26b0b820dd0f173c924887a93581ce8642 commit: 75d1ca26b0b820dd0f173c924887a93581ce8642 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2017-12-19T13:09:19-08:00 summary: Improve the F-strings and format specifier documentation (GH-4931) (GH-4933) Mention that the format-specifier mini language in f-strings is the same one used by str.format. (cherry picked from commit f4e21a2a72f76d75a6cc6f74faf910a5f3108482) files: M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 30dc72184ae..c0f2ee59b8c 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -654,10 +654,11 @@ expression or conversion result. An empty string is passed when the format specifier is omitted. The formatted result is then included in the final value of the whole string. -Top-level format specifiers may include nested replacement fields. -These nested fields may include their own conversion fields and -:ref:`format specifiers `, but may not include more -deeply-nested replacement fields. +Top-level format specifiers may include nested replacement fields. These nested +fields may include their own conversion fields and :ref:`format specifiers +`, but may not include more deeply-nested replacement fields. The +:ref:`format specifier mini-language ` is the same as that used by +the string .format() method. Formatted string literals may be concatenated, but replacement fields cannot be split across literals. From webhook-mailer at python.org Tue Dec 19 17:48:20 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 19 Dec 2017 22:48:20 -0000 Subject: [Python-checkins] bpo-32030: Add _PyCoreConfig.argv (#4934) Message-ID: https://github.com/python/cpython/commit/c4bca951065f4b2b6833f6ce7a0721e863e2343e commit: c4bca951065f4b2b6833f6ce7a0721e863e2343e branch: master author: Victor Stinner committer: GitHub date: 2017-12-19T23:48:17+01:00 summary: bpo-32030: Add _PyCoreConfig.argv (#4934) * Add argc and argv to _PyCoreConfig * _PyMainInterpreterConfig_Read() now builds its argv from _PyCoreConfig.arg * Move _PyMain.env_warning_options into _Py_CommandLineDetails * Reorder pymain_free() files: M Include/pylifecycle.h M Include/pystate.h M Modules/main.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 3ea8ad65088..77c4330ebcc 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -61,7 +61,9 @@ PyAPI_FUNC(int) _PyCoreConfig_Copy( _PyCoreConfig *config, const _PyCoreConfig *config2); -PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *, _PyCoreConfig *); +PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read( + _PyMainInterpreterConfig *config, + const _PyCoreConfig *core_config); PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *); PyAPI_FUNC(int) _PyMainInterpreterConfig_Copy( _PyMainInterpreterConfig *config, diff --git a/Include/pystate.h b/Include/pystate.h index fff134a4970..ed5b6c9bd1a 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -47,10 +47,18 @@ typedef struct { wchar_t *home; /* PYTHONHOME environment variable, see also Py_SetPythonHome(). */ wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ + + int argc; /* Number of command line arguments, + -1 means unset */ + wchar_t **argv; /* sys.argv, ignored if argc is negative */ } _PyCoreConfig; #define _PyCoreConfig_INIT \ - (_PyCoreConfig){.use_hash_seed = -1, .coerce_c_locale = -1, .utf8_mode = -1} + (_PyCoreConfig){ \ + .use_hash_seed = -1, \ + .coerce_c_locale = -1, \ + .utf8_mode = -1, \ + .argc = -1} /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ /* Placeholders while working on the new configuration API diff --git a/Modules/main.c b/Modules/main.c index 360a0859d4c..59e535d6ae7 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -229,7 +229,7 @@ pymain_run_interactive_hook(void) static int -pymain_run_module(wchar_t *modname, int set_argv0) +pymain_run_module(const wchar_t *modname, int set_argv0) { PyObject *module, *runpy, *runmodule, *runargs, *result; runpy = PyImport_ImportModule("runpy"); @@ -279,7 +279,7 @@ pymain_run_module(wchar_t *modname, int set_argv0) } static PyObject * -pymain_get_importer(wchar_t *filename) +pymain_get_importer(const wchar_t *filename) { PyObject *sys_path0 = NULL, *importer; @@ -384,9 +384,10 @@ typedef struct { } _Py_OptList; typedef struct { - wchar_t *filename; /* Trailing arg without -c or -m */ + wchar_t **argv; + const wchar_t *filename; /* Trailing arg without -c or -m */ wchar_t *command; /* -c argument */ - wchar_t *module; /* -m argument */ + const wchar_t *module; /* -m argument */ _Py_OptList warning_options; /* -W options */ int print_help; /* -h, -? options */ int print_version; /* -V option */ @@ -411,6 +412,7 @@ typedef struct { int legacy_windows_stdio; /* Py_LegacyWindowsStdioFlag, PYTHONLEGACYWINDOWSSTDIO */ #endif + _Py_OptList env_warning_options; /* PYTHONWARNINGS env var */ } _Py_CommandLineDetails; /* Structure used by Py_Main() to pass data to subfunctions */ @@ -429,16 +431,11 @@ typedef struct { int run_code; /* Error message if a function failed */ _PyInitError err; - /* PYTHONWARNINGS env var */ - _Py_OptList env_warning_options; int argc; - wchar_t **argv; int use_bytes_argv; char **bytes_argv; - - int sys_argc; - wchar_t **sys_argv; + wchar_t **wchar_argv; } _PyMain; /* .cmdline is initialized to zeros */ @@ -462,118 +459,141 @@ pymain_optlist_clear(_Py_OptList *list) } -/* Free global variables which cannot be freed in Py_Finalize(): - configuration options set before Py_Initialize() which should - remain valid after Py_Finalize(), since Py_Initialize()/Py_Finalize() can - be called multiple times. - - Called with the current memory allocators. */ static void -pymain_free_globals(_PyMain *pymain) +clear_argv(int argc, wchar_t **argv) { - _PyPathConfig_Clear(&_Py_path_config); - _PyImport_Fini2(); - -#ifdef __INSURE__ - /* Insure++ is a memory analysis tool that aids in discovering - * memory leaks and other memory problems. On Python exit, the - * interned string dictionaries are flagged as being in use at exit - * (which it is). Under normal circumstances, this is fine because - * the memory will be automatically reclaimed by the system. Under - * memory debugging, it's a huge source of useless noise, so we - * trade off slower shutdown for less distraction in the memory - * reports. -baw - */ - _Py_ReleaseInternedUnicodeStrings(); -#endif /* __INSURE__ */ -} - - -/* Clear argv allocated by pymain_decode_bytes_argv() */ -static void -pymain_clear_bytes_argv(_PyMain *pymain, int argc) -{ - if (pymain->use_bytes_argv && pymain->argv != NULL) { - for (int i = 0; i < argc; i++) { - PyMem_RawFree(pymain->argv[i]); - } - PyMem_RawFree(pymain->argv); - pymain->argv = NULL; + for (int i=0; i < argc; i++) { + PyMem_RawFree(argv[i]); } + PyMem_RawFree(argv); } static int -pymain_decode_bytes_argv(_PyMain *pymain) +pymain_init_cmdline_argv(_PyMain *pymain) { - assert(pymain->argv == NULL); + assert(pymain->cmdline.argv == NULL); + + if (!pymain->use_bytes_argv) { + pymain->cmdline.argv = pymain->wchar_argv; + return 0; + } /* +1 for a the NULL terminator */ size_t size = sizeof(wchar_t*) * (pymain->argc + 1); - pymain->argv = (wchar_t **)PyMem_RawMalloc(size); - if (pymain->argv == NULL) { + wchar_t** argv = (wchar_t **)PyMem_RawMalloc(size); + if (argv == NULL) { pymain->err = _Py_INIT_NO_MEMORY(); return -1; } for (int i = 0; i < pymain->argc; i++) { size_t len; - pymain->argv[i] = Py_DecodeLocale(pymain->bytes_argv[i], &len); - if (pymain->argv[i] == NULL) { - pymain_clear_bytes_argv(pymain, i); + wchar_t *arg = Py_DecodeLocale(pymain->bytes_argv[i], &len); + if (arg == NULL) { + clear_argv(i, argv); pymain->err = DECODE_LOCALE_ERR("command line arguments", (Py_ssize_t)len); return -1; } + argv[i] = arg; } - pymain->argv[pymain->argc] = NULL; + argv[pymain->argc] = NULL; + + pymain->cmdline.argv = argv; return 0; } static void -pymain_clear_pymain(_PyMain *pymain) +pymain_clear_cmdline(_PyMain *pymain) { + /* Clear orig_argv: pymain_init_python_core() uses a borrowed pointer + to pymain->argv */ + orig_argc = 0; + orig_argv = NULL; + _Py_CommandLineDetails *cmdline = &pymain->cmdline; pymain_optlist_clear(&cmdline->warning_options); pymain_optlist_clear(&cmdline->xoptions); PyMem_RawFree(cmdline->command); cmdline->command = NULL; + pymain_optlist_clear(&cmdline->env_warning_options); + + if (pymain->use_bytes_argv && cmdline->argv != NULL) { + clear_argv(pymain->argc, cmdline->argv); + } + cmdline->argv = NULL; +} + - PyMem_RawFree(pymain->sys_argv); - pymain->sys_argv = NULL; - pymain_optlist_clear(&pymain->env_warning_options); - pymain_clear_bytes_argv(pymain, pymain->argc); +static void +pymain_clear_configs(_PyMain *pymain) +{ + _PyMainInterpreterConfig_Clear(&pymain->config); + + /* Clear core config with the memory allocator + used by pymain_read_conf() */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); _PyCoreConfig_Clear(&pymain->core_config); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } -/* Clear Python ojects */ static void -pymain_clear_python(_PyMain *pymain) +pymain_free_python(_PyMain *pymain) { Py_CLEAR(pymain->main_importer_path); - _PyMainInterpreterConfig_Clear(&pymain->config); + +#ifdef __INSURE__ + /* Insure++ is a memory analysis tool that aids in discovering + * memory leaks and other memory problems. On Python exit, the + * interned string dictionaries are flagged as being in use at exit + * (which it is). Under normal circumstances, this is fine because + * the memory will be automatically reclaimed by the system. Under + * memory debugging, it's a huge source of useless noise, so we + * trade off slower shutdown for less distraction in the memory + * reports. -baw + */ + _Py_ReleaseInternedUnicodeStrings(); +#endif /* __INSURE__ */ } static void -pymain_free(_PyMain *pymain) +pymain_free_raw(_PyMain *pymain) { + _PyImport_Fini2(); + + /* Free global variables which cannot be freed in Py_Finalize(): + configuration options set before Py_Initialize() which should + remain valid after Py_Finalize(), since + Py_Initialize()-Py_Finalize() can be called multiple times. */ + _PyPathConfig_Clear(&_Py_path_config); + /* Force the allocator used by pymain_read_conf() */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - pymain_clear_python(pymain); - pymain_clear_pymain(pymain); - pymain_free_globals(pymain); + _PyCoreConfig_Clear(&pymain->core_config); + pymain_clear_cmdline(pymain); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } +static void +pymain_free(_PyMain *pymain) +{ + pymain_free_python(pymain); + pymain_free_raw(pymain); +} + + static int pymain_run_main_from_importer(_PyMain *pymain) { @@ -645,7 +665,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain) _PyOS_ResetGetOpt(); do { int longindex = -1; - int c = _PyOS_GetOpt(pymain->argc, pymain->argv, PROGRAM_OPTS, + int c = _PyOS_GetOpt(pymain->argc, cmdline->argv, PROGRAM_OPTS, longoptions, &longindex); if (c == EOF) { break; @@ -791,9 +811,9 @@ pymain_parse_cmdline_impl(_PyMain *pymain) if (cmdline->command == NULL && cmdline->module == NULL && _PyOS_optind < pymain->argc - && wcscmp(pymain->argv[_PyOS_optind], L"-") != 0) + && wcscmp(cmdline->argv[_PyOS_optind], L"-") != 0) { - cmdline->filename = pymain->argv[_PyOS_optind]; + cmdline->filename = cmdline->argv[_PyOS_optind]; } pymain->run_code = (cmdline->command != NULL || cmdline->filename != NULL @@ -947,7 +967,7 @@ pymain_init_warnoptions(_PyMain *pymain) if (pymain_add_warning_dev_mode(warnoptions, &pymain->core_config) < 0) { goto error; } - if (pymain_add_warnings_optlist(warnoptions, &pymain->env_warning_options) < 0) { + if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.env_warning_options) < 0) { goto error; } if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.warning_options) < 0) { @@ -990,7 +1010,7 @@ pymain_warnings_envvar(_PyMain *pymain) warning != NULL; warning = wcstok_s(NULL, L",", &context)) { - if (pymain_optlist_append(pymain, &pymain->env_warning_options, + if (pymain_optlist_append(pymain, &pymain->cmdline.env_warning_options, warning) < 0) { PyMem_RawFree(buf); return -1; @@ -1020,7 +1040,7 @@ pymain_warnings_envvar(_PyMain *pymain) SET_DECODE_ERROR("PYTHONWARNINGS environment variable", len); return -1; } - if (pymain_optlist_append(pymain, &pymain->env_warning_options, + if (pymain_optlist_append(pymain, &pymain->cmdline.env_warning_options, warning) < 0) { PyMem_RawFree(warning); return -1; @@ -1142,7 +1162,7 @@ pymain_get_program_name(_PyMain *pymain) { if (pymain->core_config.program_name == NULL) { /* Use argv[0] by default */ - pymain->core_config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); + pymain->core_config.program_name = pymain_wstrdup(pymain, pymain->cmdline.argv[0]); if (pymain->core_config.program_name == NULL) { return -1; } @@ -1170,66 +1190,102 @@ pymain_header(_PyMain *pymain) } +static wchar_t** +copy_argv(int argc, wchar_t **argv) +{ + assert(argc >= 0 && argv != NULL); + size_t size = argc * sizeof(argv[0]); + wchar_t **argv_copy = PyMem_RawMalloc(size); + for (int i=0; i < argc; i++) { + wchar_t* arg = _PyMem_RawWcsdup(argv[i]); + if (arg == NULL) { + clear_argv(i, argv); + return NULL; + } + argv_copy[i] = arg; + } + return argv_copy; +} + + static int -pymain_init_argv(_PyMain *pymain) +pymain_init_core_argv(_PyMain *pymain) { - int argc = pymain->sys_argc; - wchar_t** argv = pymain->sys_argv; + _Py_CommandLineDetails *cmdline = &pymain->cmdline; + + /* Copy argv to be able to modify it (to force -c/-m) */ + int argc = pymain->argc - _PyOS_optind; + wchar_t **argv; - if (argc <= 0 || pymain->sys_argv == NULL) { + if (argc <= 0 || cmdline->argv == NULL) { /* Ensure at least one (empty) argument is seen */ static wchar_t *empty_argv[1] = {L""}; - argv = empty_argv; argc = 1; + argv = copy_argv(1, empty_argv); + } + else { + argv = copy_argv(argc, &cmdline->argv[_PyOS_optind]); } - PyObject *list = PyList_New(argc); - if (list == NULL) { + if (argv == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - for (int i = 0; i < argc; i++) { - PyObject *v = PyUnicode_FromWideChar(argv[i], -1); - if (v == NULL) { - Py_DECREF(list); + wchar_t *arg0 = NULL; + if (cmdline->command != NULL) { + /* Force sys.argv[0] = '-c' */ + arg0 = L"-c"; + } + else if (cmdline->module != NULL) { + /* Force sys.argv[0] = '-m'*/ + arg0 = L"-m"; + } + if (arg0 != NULL) { + arg0 = _PyMem_RawWcsdup(arg0); + if (arg0 == NULL) { + clear_argv(argc, argv); + pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - PyList_SET_ITEM(list, i, v); + PyMem_RawFree(argv[0]); + argv[0] = arg0; } - pymain->config.argv = list; + pymain->core_config.argc = argc; + pymain->core_config.argv = argv; return 0; } static int -pymain_init_sys_argv(_PyMain *pymain) +config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_config) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; + assert(config->argv == NULL); - if (cmdline->command != NULL || cmdline->module != NULL) { - /* Backup _PyOS_optind */ - _PyOS_optind--; + if (core_config->argc < 0) { + return 0; } - /* Copy argv to be able to modify it (to force -c/-m) */ - pymain->sys_argc = pymain->argc - _PyOS_optind; - size_t size = pymain->sys_argc * sizeof(pymain->argv[0]); - pymain->sys_argv = PyMem_RawMalloc(size); - if (pymain->sys_argv == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); + int argc = core_config->argc; + wchar_t** argv = core_config->argv; + assert(argc >= 1 && argv != NULL); + + PyObject *list = PyList_New(argc); + if (list == NULL) { return -1; } - memcpy(pymain->sys_argv, &pymain->argv[_PyOS_optind], size); - if (cmdline->command != NULL) { - /* Force sys.argv[0] = '-c' */ - pymain->sys_argv[0] = L"-c"; - } - else if (cmdline->module != NULL) { - /* Force sys.argv[0] = '-m'*/ - pymain->sys_argv[0] = L"-m"; + for (int i = 0; i < argc; i++) { + PyObject *v = PyUnicode_FromWideChar(argv[i], -1); + if (v == NULL) { + Py_DECREF(list); + return -1; + } + PyList_SET_ITEM(list, i, v); } + + config->argv = list; return 0; } @@ -1254,7 +1310,7 @@ pymain_update_sys_path(_PyMain *pymain) return -1; } - PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->sys_argc, pymain->sys_argv); + PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc, pymain->core_config.argv); if (path0 == NULL) { pymain->err = _Py_INIT_NO_MEMORY(); return -1; @@ -1374,7 +1430,7 @@ pymain_open_filename(_PyMain *pymain) else cfilename = ""; fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n", - pymain->argv[0], cfilename, err, strerror(err)); + cmdline->argv[0], cfilename, err, strerror(err)); PyMem_Free(cfilename_buffer); pymain->status = 2; return NULL; @@ -1397,7 +1453,7 @@ pymain_open_filename(_PyMain *pymain) S_ISDIR(sb.st_mode)) { fprintf(stderr, "%ls: '%ls' is a directory, cannot continue\n", - pymain->argv[0], cmdline->filename); + cmdline->argv[0], cmdline->filename); fclose(fp); pymain->status = 1; return NULL; @@ -1474,11 +1530,16 @@ pymain_parse_cmdline(_PyMain *pymain) return -1; } if (res) { - pymain_usage(1, pymain->argv[0]); + pymain_usage(1, pymain->cmdline.argv[0]); pymain->status = 2; return 1; } + if (pymain->cmdline.command != NULL || pymain->cmdline.module != NULL) { + /* Backup _PyOS_optind */ + _PyOS_optind--; + } + return 0; } @@ -1912,7 +1973,7 @@ pymain_read_conf_impl(_PyMain *pymain) return -1; } - if (pymain_init_sys_argv(pymain) < 0) { + if (pymain_init_core_argv(pymain) < 0) { return -1; } @@ -1960,10 +2021,8 @@ pymain_read_conf(_PyMain *pymain) goto done; } - if (pymain->use_bytes_argv) { - if (pymain_decode_bytes_argv(pymain) < 0) { - goto done; - } + if (pymain_init_cmdline_argv(pymain) < 0) { + goto done; } res = pymain_read_conf_impl(pymain); @@ -2008,7 +2067,8 @@ pymain_read_conf(_PyMain *pymain) pymain_read_conf_impl(). */ Py_UTF8Mode = pymain->core_config.utf8_mode; Py_IgnoreEnvironmentFlag = init_ignore_env; - pymain_clear_pymain(pymain); + _PyCoreConfig_Clear(&pymain->core_config); + pymain_clear_cmdline(pymain); pymain_get_global_config(pymain); /* The encoding changed: read again the configuration @@ -2089,6 +2149,12 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) CLEAR(config->home); CLEAR(config->program_name); #undef CLEAR + + if (config->argc >= 0) { + clear_argv(config->argc, config->argv); + config->argc = -1; + config->argv = NULL; + } } @@ -2098,6 +2164,16 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) _PyCoreConfig_Clear(config); #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR +#define COPY_STR_ATTR(ATTR) \ + do { \ + if (config2->ATTR != NULL) { \ + config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \ + if (config->ATTR == NULL) { \ + return -1; \ + } \ + } \ + } while (0) + COPY_ATTR(ignore_environment); COPY_ATTR(use_hash_seed); COPY_ATTR(hash_seed); @@ -2112,21 +2188,21 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_ATTR(dump_refs); COPY_ATTR(malloc_stats); COPY_ATTR(utf8_mode); -#undef COPY_ATTR - -#define COPY_STR_ATTR(ATTR) \ - do { \ - if (config2->ATTR != NULL) { \ - config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \ - if (config->ATTR == NULL) { \ - return -1; \ - } \ - } \ - } while (0) COPY_STR_ATTR(module_search_path_env); COPY_STR_ATTR(home); COPY_STR_ATTR(program_name); + + if (config2->argc >= 0) { + wchar_t **argv = copy_argv(config2->argc, config2->argv); + if (argv == NULL) { + return -1; + } + config->argv = argv; + } + COPY_ATTR(argc); + +#undef COPY_ATTR #undef COPY_STR_ATTR return 0; } @@ -2241,13 +2317,17 @@ config_create_path_list(const wchar_t *path, wchar_t delim) _PyInitError -_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) +_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_config) { _PyInitError err = _PyPathConfig_Init(core_config); if (_Py_INIT_FAILED(err)) { return err; } + if (config_init_argv(config, core_config) < 0) { + return _Py_INIT_ERR("failed to create sys.argv"); + } + /* Signal handlers are installed by default */ if (config->install_signal_handlers < 0) { config->install_signal_handlers = 1; @@ -2324,10 +2404,6 @@ pymain_init_python_main(_PyMain *pymain) pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - if (pymain_init_argv(pymain) < 0) { - pymain->err = _Py_INIT_ERR("failed to create sys.argv"); - return -1; - } _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config, &pymain->core_config); @@ -2378,9 +2454,11 @@ pymain_run_python(_PyMain *pymain) } -static int +static void pymain_init(_PyMain *pymain) { + memset(&pymain->cmdline, 0, sizeof(pymain->cmdline)); + /* 754 requires that FP exceptions run in "no stop" mode by default, * and until C vendors implement C99's ways to control FP exceptions, * Python requires non-stop mode. Alas, some platforms enable FP @@ -2390,23 +2468,18 @@ pymain_init(_PyMain *pymain) fedisableexcept(FE_OVERFLOW); #endif - pymain->err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(pymain->err)) { - return -1; - } - pymain->core_config._disable_importlib = 0; pymain->config.install_signal_handlers = 1; pymain_get_global_config(pymain); - return 0; } static int pymain_impl(_PyMain *pymain) { - if (pymain_init(pymain) < 0) { + pymain->err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(pymain->err)) { return -1; } @@ -2423,7 +2496,7 @@ pymain_impl(_PyMain *pymain) _Py_CommandLineDetails *cmdline = &pymain->cmdline; if (cmdline->print_help) { - pymain_usage(0, pymain->argv[0]); + pymain_usage(0, cmdline->argv[0]); return 0; } @@ -2433,8 +2506,9 @@ pymain_impl(_PyMain *pymain) return 0; } - orig_argc = pymain->argc; /* For Py_GetArgcArgv() */ - orig_argv = pymain->argv; + /* For Py_GetArgcArgv(). Cleared by pymain_free(). */ + orig_argc = pymain->argc; + orig_argv = cmdline->argv; res = pymain_init_python_core(pymain); if (res < 0) { @@ -2446,9 +2520,9 @@ pymain_impl(_PyMain *pymain) return -1; } - pymain_run_python(pymain); + pymain_clear_configs(pymain); - pymain_clear_python(pymain); + pymain_run_python(pymain); if (Py_FinalizeEx() < 0) { /* Value unlikely to be confused with a non-error exit status or @@ -2462,16 +2536,13 @@ pymain_impl(_PyMain *pymain) static int pymain_main(_PyMain *pymain) { - memset(&pymain->cmdline, 0, sizeof(pymain->cmdline)); + pymain_init(pymain); if (pymain_impl(pymain) < 0) { _Py_FatalInitError(pymain->err); } pymain_free(pymain); - orig_argc = 0; - orig_argv = NULL; - return pymain->status; } @@ -2480,8 +2551,9 @@ int Py_Main(int argc, wchar_t **argv) { _PyMain pymain = _PyMain_INIT; + pymain.use_bytes_argv = 0; pymain.argc = argc; - pymain.argv = argv; + pymain.wchar_argv = argv; return pymain_main(&pymain); } @@ -2491,8 +2563,8 @@ int _Py_UnixMain(int argc, char **argv) { _PyMain pymain = _PyMain_INIT; - pymain.argc = argc; pymain.use_bytes_argv = 1; + pymain.argc = argc; pymain.bytes_argv = argv; return pymain_main(&pymain); From webhook-mailer at python.org Tue Dec 19 19:42:02 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 20 Dec 2017 00:42:02 -0000 Subject: [Python-checkins] bpo-32030: Cleanup pymain_main() (#4935) Message-ID: https://github.com/python/cpython/commit/19760863623b636a63ccf649107d9504c6465a92 commit: 19760863623b636a63ccf649107d9504c6465a92 branch: master author: Victor Stinner committer: GitHub date: 2017-12-20T01:41:59+01:00 summary: bpo-32030: Cleanup pymain_main() (#4935) * Reorganize pymain_main() to make the code more flat * Clear configurations before pymain_update_sys_path() * Mark Py_FatalError() and _Py_FatalInitError() with _Py_NO_RETURN * Replace _PyMain.run_code variable with a new RUN_CODE() macro * Move _PyMain.cf into a local variable in pymain_run_python() files: M Modules/main.c M Python/pylifecycle.c diff --git a/Modules/main.c b/Modules/main.c index 59e535d6ae7..429ecbc767d 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -389,6 +389,7 @@ typedef struct { wchar_t *command; /* -c argument */ const wchar_t *module; /* -m argument */ _Py_OptList warning_options; /* -W options */ + _Py_OptList env_warning_options; /* PYTHONWARNINGS env var */ int print_help; /* -h, -? options */ int print_version; /* -V option */ int bytes_warning; /* Py_BytesWarningFlag, -b */ @@ -412,41 +413,47 @@ typedef struct { int legacy_windows_stdio; /* Py_LegacyWindowsStdioFlag, PYTHONLEGACYWINDOWSSTDIO */ #endif - _Py_OptList env_warning_options; /* PYTHONWARNINGS env var */ } _Py_CommandLineDetails; /* Structure used by Py_Main() to pass data to subfunctions */ typedef struct { - /* Exit status ("exit code") */ + /* Input arguments */ + int argc; + int use_bytes_argv; + char **bytes_argv; + wchar_t **wchar_argv; + + /* Exit status or "exit code": result of pymain_main() */ int status; - PyCompilerFlags cf; + /* Error message if a function failed */ + _PyInitError err; + + _Py_CommandLineDetails cmdline; /* non-zero is stdin is a TTY or if -i option is used */ int stdin_is_interactive; + _PyCoreConfig core_config; _PyMainInterpreterConfig config; - _Py_CommandLineDetails cmdline; - PyObject *main_importer_path; - /* non-zero if filename, command (-c) or module (-m) is set - on the command line */ - int run_code; - /* Error message if a function failed */ - _PyInitError err; - int argc; - int use_bytes_argv; - char **bytes_argv; - wchar_t **wchar_argv; + PyObject *main_importer_path; } _PyMain; /* .cmdline is initialized to zeros */ #define _PyMain_INIT \ {.core_config = _PyCoreConfig_INIT, \ .config = _PyMainInterpreterConfig_INIT, \ - .run_code = -1, \ .err = _Py_INIT_OK()} /* Note: _PyMain_INIT sets other fields to 0/NULL */ +/* Non-zero if filename, command (-c) or module (-m) is set + on the command line */ +#define RUN_CODE(pymain) \ + (pymain->cmdline.command != NULL \ + || pymain->cmdline.filename != NULL \ + || pymain->cmdline.module != NULL) + + static void pymain_optlist_clear(_Py_OptList *list) { @@ -526,7 +533,6 @@ pymain_clear_cmdline(_PyMain *pymain) cmdline->argv = NULL; } - static void pymain_clear_configs(_PyMain *pymain) { @@ -816,9 +822,6 @@ pymain_parse_cmdline_impl(_PyMain *pymain) cmdline->filename = cmdline->argv[_PyOS_optind]; } - pymain->run_code = (cmdline->command != NULL || cmdline->filename != NULL - || cmdline->module != NULL); - /* -c and -m options are exclusive */ assert(!(cmdline->command != NULL && cmdline->module != NULL)); @@ -1174,12 +1177,11 @@ pymain_get_program_name(_PyMain *pymain) static void pymain_header(_PyMain *pymain) { - /* TODO: Move this to _PyRun_PrepareMain */ if (Py_QuietFlag) { return; } - if (!Py_VerboseFlag && (pymain->run_code || !pymain->stdin_is_interactive)) { + if (!Py_VerboseFlag && (RUN_CODE(pymain) || !pymain->stdin_is_interactive)) { return; } @@ -1291,17 +1293,32 @@ config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_con static int -pymain_update_sys_path(_PyMain *pymain) +pymain_init_path0(_PyMain *pymain, PyObject **path0) { if (pymain->main_importer_path != NULL) { /* Let pymain_run_main_from_importer() adjust sys.path[0] later */ + *path0 = NULL; return 0; } if (Py_IsolatedFlag) { + *path0 = NULL; return 0; } + *path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc, + pymain->core_config.argv); + if (*path0 == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } + return 0; +} + + +static int +pymain_update_sys_path(_PyMain *pymain, PyObject *path0) +{ /* Prepend argv[0] to sys.path. If argv[0] is a symlink, use the real path. */ PyObject *sys_path = PySys_GetObject("path"); @@ -1310,20 +1327,11 @@ pymain_update_sys_path(_PyMain *pymain) return -1; } - PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc, pymain->core_config.argv); - if (path0 == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; - } - /* Prepend path0 to sys.path */ if (PyList_Insert(sys_path, 0, path0) < 0) { - Py_DECREF(path0); pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); return -1; } - Py_DECREF(path0); - return 0; } @@ -1357,7 +1365,7 @@ pymain_get_global_config(_PyMain *pymain) } -/* Set Py_XXX global configuration variables */ +/* Set Py_xxx global configuration variables */ static void pymain_set_global_config(_PyMain *pymain) { @@ -1396,7 +1404,7 @@ pymain_import_readline(_PyMain *pymain) if (Py_IsolatedFlag) { return; } - if (!Py_InspectFlag && pymain->run_code) { + if (!Py_InspectFlag && RUN_CODE(pymain)) { return; } if (!isatty(fileno(stdin))) { @@ -1464,13 +1472,13 @@ pymain_open_filename(_PyMain *pymain) static void -pymain_run_filename(_PyMain *pymain) +pymain_run_filename(_PyMain *pymain, PyCompilerFlags *cf) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; if (cmdline->filename == NULL && pymain->stdin_is_interactive) { Py_InspectFlag = 0; /* do exit on SystemExit */ - pymain_run_startup(&pymain->cf); + pymain_run_startup(cf); pymain_run_interactive_hook(); } @@ -1490,12 +1498,12 @@ pymain_run_filename(_PyMain *pymain) fp = stdin; } - pymain->status = pymain_run_file(fp, cmdline->filename, &pymain->cf); + pymain->status = pymain_run_file(fp, cmdline->filename, cf); } static void -pymain_repl(_PyMain *pymain) +pymain_repl(_PyMain *pymain, PyCompilerFlags *cf) { /* Check this environment variable at the end, to give programs the opportunity to set it from Python. */ @@ -1503,15 +1511,14 @@ pymain_repl(_PyMain *pymain) Py_InspectFlag = 1; } - if (!(Py_InspectFlag && pymain->stdin_is_interactive - && pymain->run_code)) { + if (!(Py_InspectFlag && pymain->stdin_is_interactive && RUN_CODE(pymain))) { return; } Py_InspectFlag = 0; pymain_run_interactive_hook(); - int res = PyRun_AnyFileFlags(stdin, "", &pymain->cf); + int res = PyRun_AnyFileFlags(stdin, "", cf); pymain->status = (res != 0); } @@ -1966,6 +1973,10 @@ pymain_read_conf_impl(_PyMain *pymain) return res; } + if (pymain_init_core_argv(pymain) < 0) { + return -1; + } + /* Set Py_IgnoreEnvironmentFlag for Py_GETENV() */ Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; @@ -1973,10 +1984,6 @@ pymain_read_conf_impl(_PyMain *pymain) return -1; } - if (pymain_init_core_argv(pymain) < 0) { - return -1; - } - _PyInitError err = _PyCoreConfig_Read(&pymain->core_config); if (_Py_INIT_FAILED(err)) { pymain->err = err; @@ -1986,6 +1993,8 @@ pymain_read_conf_impl(_PyMain *pymain) } +/* Read the configuration, but initialize also the LC_CTYPE locale: + enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */ static int pymain_read_conf(_PyMain *pymain) { @@ -2426,9 +2435,21 @@ pymain_init_python_main(_PyMain *pymain) pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename); } - if (pymain_update_sys_path(pymain) < 0) { + PyObject *path0; + if (pymain_init_path0(pymain, &path0) < 0) { return -1; } + + pymain_clear_configs(pymain); + + if (path0 != NULL) { + if (pymain_update_sys_path(pymain, path0) < 0) { + Py_DECREF(path0); + return -1; + } + Py_DECREF(path0); + } + return 0; } @@ -2436,21 +2457,22 @@ pymain_init_python_main(_PyMain *pymain) static void pymain_run_python(_PyMain *pymain) { + PyCompilerFlags cf = {.cf_flags = 0}; _Py_CommandLineDetails *cmdline = &pymain->cmdline; pymain_header(pymain); pymain_import_readline(pymain); if (cmdline->command) { - pymain->status = pymain_run_command(cmdline->command, &pymain->cf); + pymain->status = pymain_run_command(cmdline->command, &cf); } else if (cmdline->module) { pymain->status = (pymain_run_module(cmdline->module, 1) != 0); } else { - pymain_run_filename(pymain); + pymain_run_filename(pymain, &cf); } - pymain_repl(pymain); + pymain_repl(pymain, &cf); } @@ -2476,51 +2498,61 @@ pymain_init(_PyMain *pymain) static int -pymain_impl(_PyMain *pymain) +pymain_init_cmdline(_PyMain *pymain) { pymain->err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(pymain->err)) { return -1; } - /* Read the configuration, but initialize also the LC_CTYPE locale: - enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */ int res = pymain_read_conf(pymain); if (res < 0) { return -1; } if (res > 0) { /* --help or --version command: we are done */ - return 0; + return 1; } _Py_CommandLineDetails *cmdline = &pymain->cmdline; if (cmdline->print_help) { pymain_usage(0, cmdline->argv[0]); - return 0; + return 1; } if (cmdline->print_version) { printf("Python %s\n", (cmdline->print_version >= 2) ? Py_GetVersion() : PY_VERSION); - return 0; + return 1; } /* For Py_GetArgcArgv(). Cleared by pymain_free(). */ orig_argc = pymain->argc; orig_argv = cmdline->argv; + return 0; +} - res = pymain_init_python_core(pymain); + +static int +pymain_main(_PyMain *pymain) +{ + pymain_init(pymain); + + int res = pymain_init_cmdline(pymain); if (res < 0) { - return -1; + _Py_FatalInitError(pymain->err); + } + if (res == 1) { + goto done; } - res = pymain_init_python_main(pymain); - if (res < 0) { - return -1; + if (pymain_init_python_core(pymain) < 0) { + _Py_FatalInitError(pymain->err); } - pymain_clear_configs(pymain); + if (pymain_init_python_main(pymain) < 0) { + _Py_FatalInitError(pymain->err); + } pymain_run_python(pymain); @@ -2529,18 +2561,8 @@ pymain_impl(_PyMain *pymain) other special meaning */ pymain->status = 120; } - return 0; -} - -static int -pymain_main(_PyMain *pymain) -{ - pymain_init(pymain); - - if (pymain_impl(pymain) < 0) { - _Py_FatalInitError(pymain->err); - } +done: pymain_free(pymain); return pymain->status; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 678fbb63cc8..090694f7cae 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2003,13 +2003,13 @@ fatal_error(const char *prefix, const char *msg, int status) } } -void +void _Py_NO_RETURN Py_FatalError(const char *msg) { fatal_error(NULL, msg, -1); } -void +void _Py_NO_RETURN _Py_FatalInitError(_PyInitError err) { /* On "user" error: exit with status 1. From lp_benchmark_robot at intel.com Tue Dec 19 20:59:59 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Tue, 19 Dec 2017 17:59:59 -0800 Subject: [Python-checkins] [1 up, 64 flat] Results for Python (master branch) 2017-12-19 Message-ID: Results for project python/master, build date: 2017-12-19 03:03:44-08:00. - commit: 5d86246 - previous commit: b2a6083 - revision date: 2017-12-19 11:35:58+01:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.837% | +0.155% | +5.278% | +7.602% | +-----+------------------------+--------+------------+------------+------------+ | :-) | call_method| 1.418% | +5.725% | +25.877% | +9.146% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.820% | +3.178% | +25.965% | +8.428% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.911% | +3.213% | +23.340% | +8.975% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.418% | +1.494% | +9.034% | +8.786% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.488% | -2.240% | +8.529% | +12.986% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.129% | +0.399% | +6.053% | +10.307% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.489% | +1.006% | -0.771% | +9.117% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 2.548% | +1.171% | +10.587% | +16.118% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.922% | -0.638% | +11.273% | +15.138% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.013% | -0.051% | +4.119% | +7.643% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.321% | +0.282% | +6.017% | +5.240% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.011% | -0.152% | +1.291% | +7.427% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.067% | +0.272% | +11.896% | +10.729% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.653% | -0.235% | +8.601% | +10.047% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.945% | +0.682% | +5.917% | +11.369% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.278% | +0.111% | +10.372% | +10.498% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.283% | -0.054% | +8.684% | +9.183% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.424% | -0.219% | +1.568% | +10.665% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 2.978% | -4.317% | -4.591% | +17.076% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.455% | +0.347% | +7.272% | +13.178% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.536% | +1.085% | +46.757% | +11.623% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.711% | -1.565% | +6.585% | +15.859% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.423% | -1.210% | +17.197% | +12.417% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.183% | -1.738% | +9.790% | +7.427% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 2.604% | +0.004% | +3.610% | +5.480% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.565% | -0.637% | -0.447% | +1.832% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 1.737% | -0.622% | +3.793% | +7.978% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.380% | -3.483% | +1.413% | +13.039% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 2.535% | -0.342% | -0.289% | +21.758% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.208% | +0.800% | +2.266% | +22.836% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.631% | -0.299% | +3.326% | +21.910% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.682% | -0.161% | +11.005% | +9.503% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.049% | +0.123% | +0.295% | +9.886% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.134% | -0.177% | +9.972% | +5.068% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.108% | -0.327% | +0.990% | +5.171% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.113% | +0.664% | +9.810% | +12.737% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.737% | -1.556% | +3.304% | +7.356% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.423% | -1.452% | -2.344% | +10.340% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.957% | -1.317% | -6.096% | +4.874% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 0.801% | -0.314% | +4.312% | +8.711% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.145% | -0.674% | +8.281% | +14.681% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 2.609% | +0.465% | -3.424% | +5.894% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.544% | +0.539% | +26.653% | +5.858% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.894% | -1.296% | +2.125% | +7.353% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.465% | +0.267% | +13.658% | +9.489% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.559% | -1.494% | -5.210% | +3.488% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.430% | +0.367% | +5.239% | +2.218% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.068% | +0.194% | +6.799% | +6.318% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.430% | +0.498% | +6.658% | +3.722% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 5.509% | -5.059% | +16.870% | +9.496% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.058% | -0.488% | +11.395% | +7.950% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.520% | -0.668% | +8.501% | +7.200% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.082% | -0.475% | +11.078% | +8.084% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.325% | -0.794% | +10.122% | +9.603% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.679% | -0.744% | +18.231% | +14.015% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.025% | -0.210% | +5.610% | +7.219% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.061% | +0.130% | +2.019% | -0.030% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 4.946% | +0.176% | +4.606% | +22.038% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 2.066% | +1.684% | -3.296% | +16.851% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.550% | +0.141% | +7.450% | +6.832% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.742% | -0.219% | +3.893% | +9.788% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.761% | +0.344% | +2.203% | +8.051% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.400% | -2.405% | -10.802% | +15.143% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.406% | -0.089% | +5.468% | +9.547% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-up-64-flat-results-for-python-master-branch-2017-12-19 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From solipsis at pitrou.net Wed Dec 20 04:12:25 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 20 Dec 2017 09:12:25 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20171220091225.123551.2383F36B8A5467BB@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, 0, 2] memory blocks, sum=2 test_multiprocessing_forkserver leaked [-1, -1, 2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogBieKl6', '--timeout', '7200'] From webhook-mailer at python.org Wed Dec 20 05:18:05 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Wed, 20 Dec 2017 10:18:05 -0000 Subject: [Python-checkins] bpo-31901: atexit callbacks should be run at subinterpreter shutdown (#4611) Message-ID: https://github.com/python/cpython/commit/776407fe893fd42972c7e3f71423d9d86741d07c commit: 776407fe893fd42972c7e3f71423d9d86741d07c branch: master author: Marcel Plch committer: Antoine Pitrou date: 2017-12-20T11:17:58+01:00 summary: bpo-31901: atexit callbacks should be run at subinterpreter shutdown (#4611) Change atexit behavior and PEP-489 multiphase init support. files: A Misc/NEWS.d/next/Core and Builtins/2017-11-28-15-04-14.bpo-31901.mDeCLK.rst M Doc/library/atexit.rst M Include/internal/pystate.h M Include/pylifecycle.h M Include/pystate.h M Lib/test/test_atexit.py M Modules/atexitmodule.c M Programs/_testembed.c M Python/pylifecycle.c M Python/pystate.c diff --git a/Doc/library/atexit.rst b/Doc/library/atexit.rst index 5c60b604c68..c2c058e474c 100644 --- a/Doc/library/atexit.rst +++ b/Doc/library/atexit.rst @@ -20,6 +20,9 @@ at interpreter termination time they will be run in the order ``C``, ``B``, program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when :func:`os._exit` is called. +.. versionchanged:: 3.7 + When used with C-API subinterpreters, registered functions + are local to the interpreter they were registered in. .. function:: register(func, *args, **kwargs) diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 305526d136c..0b464bcb2e8 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -90,7 +90,6 @@ typedef struct pyruntimestate { #define NEXITFUNCS 32 void (*exitfuncs[NEXITFUNCS])(void); int nexitfuncs; - void (*pyexitfunc)(void); struct _gc_runtime_state gc; struct _warnings_runtime_state warnings; diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 77c4330ebcc..afeae93f008 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -92,7 +92,7 @@ PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *); * exit functions. */ #ifndef Py_LIMITED_API -PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(void)); +PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(PyObject *), PyObject *); #endif PyAPI_FUNC(int) Py_AtExit(void (*func)(void)); diff --git a/Include/pystate.h b/Include/pystate.h index ed5b6c9bd1a..3282eb9d4d5 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -131,6 +131,9 @@ typedef struct _is { PyObject *after_forkers_parent; PyObject *after_forkers_child; #endif + /* AtExit module */ + void (*pyexitfunc)(PyObject *); + PyObject *pyexitmodule; } PyInterpreterState; #endif /* !Py_LIMITED_API */ diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py index aa56388ef60..3105f6c3781 100644 --- a/Lib/test/test_atexit.py +++ b/Lib/test/test_atexit.py @@ -2,6 +2,7 @@ import unittest import io import atexit +import os from test import support from test.support import script_helper @@ -203,6 +204,24 @@ def f(): self.assertEqual(ret, 0) self.assertEqual(atexit._ncallbacks(), n) + def test_callback_on_subinterpreter_teardown(self): + # This tests if a callback is called on + # subinterpreter teardown. + expected = b"The test has passed!" + r, w = os.pipe() + + code = r"""if 1: + import os + import atexit + def callback(): + os.write({:d}, b"The test has passed!") + atexit.register(callback) + """.format(w) + ret = support.run_in_subinterp(code) + os.close(w) + self.assertEqual(os.read(r, len(expected)), expected) + os.close(r) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-11-28-15-04-14.bpo-31901.mDeCLK.rst b/Misc/NEWS.d/next/Core and Builtins/2017-11-28-15-04-14.bpo-31901.mDeCLK.rst new file mode 100644 index 00000000000..613eee0bf58 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-11-28-15-04-14.bpo-31901.mDeCLK.rst @@ -0,0 +1 @@ +The `atexit` module now has its callback stored per interpreter. diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index 35ebf08ecd3..afa1cfad6c4 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -63,15 +63,13 @@ atexit_cleanup(atexitmodule_state *modstate) /* Installed into pylifecycle.c's atexit mechanism */ static void -atexit_callfuncs(void) +atexit_callfuncs(PyObject *module) { PyObject *exc_type = NULL, *exc_value, *exc_tb, *r; atexit_callback *cb; - PyObject *module; atexitmodule_state *modstate; int i; - module = PyState_FindModule(&atexitmodule); if (module == NULL) return; modstate = GET_ATEXIT_STATE(module); @@ -185,7 +183,7 @@ Run all registered exit functions."); static PyObject * atexit_run_exitfuncs(PyObject *self, PyObject *unused) { - atexit_callfuncs(); + atexit_callfuncs(self); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; @@ -225,13 +223,15 @@ atexit_m_traverse(PyObject *self, visitproc visit, void *arg) atexitmodule_state *modstate; modstate = GET_ATEXIT_STATE(self); - for (i = 0; i < modstate->ncallbacks; i++) { - atexit_callback *cb = modstate->atexit_callbacks[i]; - if (cb == NULL) - continue; - Py_VISIT(cb->func); - Py_VISIT(cb->args); - Py_VISIT(cb->kwargs); + if (modstate != NULL) { + for (i = 0; i < modstate->ncallbacks; i++) { + atexit_callback *cb = modstate->atexit_callbacks[i]; + if (cb == NULL) + continue; + Py_VISIT(cb->func); + Py_VISIT(cb->args); + Py_VISIT(cb->kwargs); + } } return 0; } @@ -241,7 +241,9 @@ atexit_m_clear(PyObject *self) { atexitmodule_state *modstate; modstate = GET_ATEXIT_STATE(self); - atexit_cleanup(modstate); + if (modstate != NULL) { + atexit_cleanup(modstate); + } return 0; } @@ -250,8 +252,10 @@ atexit_free(PyObject *m) { atexitmodule_state *modstate; modstate = GET_ATEXIT_STATE(m); - atexit_cleanup(modstate); - PyMem_Free(modstate->atexit_callbacks); + if (modstate != NULL) { + atexit_cleanup(modstate); + PyMem_Free(modstate->atexit_callbacks); + } } PyDoc_STRVAR(atexit_unregister__doc__, @@ -310,6 +314,26 @@ upon normal program termination.\n\ Two public functions, register and unregister, are defined.\n\ "); +static int +atexit_exec(PyObject *m) { + atexitmodule_state *modstate; + + modstate = GET_ATEXIT_STATE(m); + modstate->callback_len = 32; + modstate->ncallbacks = 0; + modstate->atexit_callbacks = PyMem_New(atexit_callback*, + modstate->callback_len); + if (modstate->atexit_callbacks == NULL) + return -1; + + _Py_PyAtExit(atexit_callfuncs, m); + return 0; +} + +static PyModuleDef_Slot atexit_slots[] = { + {Py_mod_exec, atexit_exec}, + {0, NULL} +}; static struct PyModuleDef atexitmodule = { PyModuleDef_HEAD_INIT, @@ -317,7 +341,7 @@ static struct PyModuleDef atexitmodule = { atexit__doc__, sizeof(atexitmodule_state), atexit_methods, - NULL, + atexit_slots, atexit_m_traverse, atexit_m_clear, (freefunc)atexit_free @@ -326,21 +350,5 @@ static struct PyModuleDef atexitmodule = { PyMODINIT_FUNC PyInit_atexit(void) { - PyObject *m; - atexitmodule_state *modstate; - - m = PyModule_Create(&atexitmodule); - if (m == NULL) - return NULL; - - modstate = GET_ATEXIT_STATE(m); - modstate->callback_len = 32; - modstate->ncallbacks = 0; - modstate->atexit_callbacks = PyMem_New(atexit_callback*, - modstate->callback_len); - if (modstate->atexit_callbacks == NULL) - return NULL; - - _Py_PyAtExit(atexit_callfuncs); - return m; + return PyModuleDef_Init(&atexitmodule); } diff --git a/Programs/_testembed.c b/Programs/_testembed.c index a528f3e3aa0..b3d7aa442d1 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -126,7 +126,6 @@ static int test_forced_io_encoding(void) return 0; } - /********************************************************* * Test parts of the C-API that work before initialization *********************************************************/ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 090694f7cae..d82782623de 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -56,7 +56,7 @@ static _PyInitError initfsencoding(PyInterpreterState *interp); static _PyInitError initsite(void); static _PyInitError init_sys_streams(PyInterpreterState *interp); static _PyInitError initsigs(void); -static void call_py_exitfuncs(void); +static void call_py_exitfuncs(PyInterpreterState *); static void wait_for_thread_shutdown(void); static void call_ll_exitfuncs(void); extern int _PyUnicode_Init(void); @@ -1006,6 +1006,10 @@ Py_FinalizeEx(void) wait_for_thread_shutdown(); + /* Get current thread state and interpreter pointer */ + tstate = PyThreadState_GET(); + interp = tstate->interp; + /* The interpreter is still entirely intact at this point, and the * exit funcs may be relying on that. In particular, if some thread * or exit func is still waiting to do an import, the import machinery @@ -1015,11 +1019,8 @@ Py_FinalizeEx(void) * threads created thru it, so this also protects pending imports in * the threads created via Threading. */ - call_py_exitfuncs(); - /* Get current thread state and interpreter pointer */ - tstate = PyThreadState_GET(); - interp = tstate->interp; + call_py_exitfuncs(interp); /* Copy the core config, PyInterpreterState_Delete() free the core config memory */ @@ -1412,6 +1413,8 @@ Py_EndInterpreter(PyThreadState *tstate) wait_for_thread_shutdown(); + call_py_exitfuncs(interp); + if (tstate != interp->tstate_head || tstate->next != NULL) Py_FatalError("Py_EndInterpreter: not the last thread"); @@ -2023,20 +2026,28 @@ _Py_FatalInitError(_PyInitError err) # include "pythread.h" /* For the atexit module. */ -void _Py_PyAtExit(void (*func)(void)) +void _Py_PyAtExit(void (*func)(PyObject *), PyObject *module) { + PyThreadState *ts; + PyInterpreterState *is; + + ts = PyThreadState_GET(); + is = ts->interp; + /* Guard against API misuse (see bpo-17852) */ - assert(_PyRuntime.pyexitfunc == NULL || _PyRuntime.pyexitfunc == func); - _PyRuntime.pyexitfunc = func; + assert(is->pyexitfunc == NULL || is->pyexitfunc == func); + + is->pyexitfunc = func; + is->pyexitmodule = module; } static void -call_py_exitfuncs(void) +call_py_exitfuncs(PyInterpreterState *istate) { - if (_PyRuntime.pyexitfunc == NULL) + if (istate->pyexitfunc == NULL) return; - (*_PyRuntime.pyexitfunc)(); + (*istate->pyexitfunc)(istate->pyexitmodule); PyErr_Clear(); } diff --git a/Python/pystate.c b/Python/pystate.c index ec7eb450b66..028292e42fb 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -153,6 +153,8 @@ PyInterpreterState_New(void) interp->after_forkers_parent = NULL; interp->after_forkers_child = NULL; #endif + interp->pyexitfunc = NULL; + interp->pyexitmodule = NULL; HEAD_LOCK(); interp->next = _PyRuntime.interpreters.head; From webhook-mailer at python.org Wed Dec 20 09:58:24 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Wed, 20 Dec 2017 14:58:24 -0000 Subject: [Python-checkins] bpo-32379: Faster MRO computation for single inheritance (#4932) Message-ID: https://github.com/python/cpython/commit/1f1a34c3145781628e10534440017b3b43211a60 commit: 1f1a34c3145781628e10534440017b3b43211a60 branch: master author: Antoine Pitrou committer: GitHub date: 2017-12-20T15:58:21+01:00 summary: bpo-32379: Faster MRO computation for single inheritance (#4932) * bpo-32379: Faster MRO computation for single inheritance files: A Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst M Lib/test/test_descr.py M Objects/typeobject.c diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index ced25f3fc44..d24d005ccfa 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1783,6 +1783,12 @@ class C(A): def f(self): return "C" class D(B, C): pass + self.assertEqual(A.mro(), [A, object]) + self.assertEqual(A.__mro__, (A, object)) + self.assertEqual(B.mro(), [B, A, object]) + self.assertEqual(B.__mro__, (B, A, object)) + self.assertEqual(C.mro(), [C, A, object]) + self.assertEqual(C.__mro__, (C, A, object)) self.assertEqual(D.mro(), [D, B, C, A, object]) self.assertEqual(D.__mro__, (D, B, C, A, object)) self.assertEqual(D().f(), "C") diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst new file mode 100644 index 00000000000..1050c61b9ec --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst @@ -0,0 +1 @@ +Make MRO computation faster when a class inherits from a single base. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index aa907018859..849c6dc1929 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1761,6 +1761,36 @@ mro_implementation(PyTypeObject *type) return NULL; } + bases = type->tp_bases; + n = PyTuple_GET_SIZE(bases); + if (n == 1) { + /* Fast path: if there is a single base, constructing the MRO + * is trivial. + */ + PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); + Py_ssize_t k; + + if (base->tp_mro == NULL) { + PyErr_Format(PyExc_TypeError, + "Cannot extend an incomplete type '%.100s'", + base->tp_name); + return NULL; + } + k = PyTuple_GET_SIZE(base->tp_mro); + result = PyTuple_New(k + 1); + if (result == NULL) { + return NULL; + } + Py_INCREF(type); + PyTuple_SET_ITEM(result, 0, (PyObject *) type); + for (i = 0; i < k; i++) { + PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i); + Py_INCREF(cls); + PyTuple_SET_ITEM(result, i + 1, cls); + } + return result; + } + /* Find a superclass linearization that honors the constraints of the explicit lists of bases and the constraints implied by each base class. @@ -1770,9 +1800,6 @@ mro_implementation(PyTypeObject *type) to_merge is the declared list of bases. */ - bases = type->tp_bases; - n = PyTuple_GET_SIZE(bases); - to_merge = PyList_New(n+1); if (to_merge == NULL) return NULL; @@ -1830,7 +1857,12 @@ static PyObject * type_mro_impl(PyTypeObject *self) /*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/ { - return mro_implementation(self); + PyObject *seq; + seq = mro_implementation(self); + if (seq != NULL && !PyList_Check(seq)) { + Py_SETREF(seq, PySequence_List(seq)); + } + return seq; } static int From webhook-mailer at python.org Wed Dec 20 12:00:27 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 20 Dec 2017 17:00:27 -0000 Subject: [Python-checkins] bpo-32030: Add _PyCoreConfig.warnoptions (#4936) Message-ID: https://github.com/python/cpython/commit/ca719ac42b3d58f7c3bcdf63f45b6d62b08b0d01 commit: ca719ac42b3d58f7c3bcdf63f45b6d62b08b0d01 branch: master author: Victor Stinner committer: GitHub date: 2017-12-20T18:00:19+01:00 summary: bpo-32030: Add _PyCoreConfig.warnoptions (#4936) Merge _PyCoreConfig_ReadEnv() into _PyCoreConfig_Read(), and _Py_CommandLineDetails usage is now restricted to pymain_cmdline(). Changes: * _PyCoreConfig: Add nxoption, xoptions, nwarnoption and warnoptions * Add _PyCoreConfig.program: argv[0] or "" * Move filename, command, module and xoptions from _Py_CommandLineDetails to _PyMain. xoptions _Py_OptList becomes (int, wchar_t**) list. * Add pymain_cmdline() function * Rename copy_argv() to copy_wstrlist(). Rename clear_argv() to clear_wstrlist(). Remove _Py_OptList structure: use (int, wchar_t**) list instead. * Rename pymain_set_flag_from_env() to pymain_get_env_flag() * Rename pymain_set_flags_from_env() to pymain_get_env_flags() * _PyMainInterpreterConfig_Read() now creates the warnoptions from _PyCoreConfig.warnoptions * Inline pymain_add_warning_dev_mode() and pymain_add_warning_bytes_flag() into config_init_warnoptions() * Inline pymain_get_program_name() into _PyCoreConfig_Read() * _Py_CommandLineDetails: Replace warning_options with nwarnoption and warnoptions. Replace env_warning_options with nenv_warnoption and env_warnoptions. * pymain_warnings_envvar() now has a single implementation for Windows and Unix: use config_get_env_var_dup() to also get the variable as wchar_t* on Unix. files: M Include/pylifecycle.h M Include/pystate.h M Modules/main.c M Python/pathconfig.c M Python/pylifecycle.c diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index afeae93f008..da740fef23a 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -54,7 +54,6 @@ PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, PyAPI_FUNC(_PyInitError) _Py_InitializeCore(const _PyCoreConfig *); PyAPI_FUNC(int) _Py_IsCoreInitialized(void); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_ReadEnv(_PyCoreConfig *); PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *); PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); PyAPI_FUNC(int) _PyCoreConfig_Copy( diff --git a/Include/pystate.h b/Include/pystate.h index 3282eb9d4d5..619e627bf36 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -50,7 +50,14 @@ typedef struct { int argc; /* Number of command line arguments, -1 means unset */ - wchar_t **argv; /* sys.argv, ignored if argc is negative */ + wchar_t **argv; /* Command line arguments */ + wchar_t *program; /* argv[0] or "" */ + + int nxoption; /* Number of -X options */ + wchar_t **xoptions; /* -X options */ + + int nwarnoption; /* Number of warnings options */ + wchar_t **warnoptions; /* Warnings options */ } _PyCoreConfig; #define _PyCoreConfig_INIT \ diff --git a/Modules/main.c b/Modules/main.c index 429ecbc767d..385a09e2747 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -56,6 +56,12 @@ extern "C" { } \ } while (0) +#ifdef MS_WINDOWS +#define WCSTOK wcstok_s +#else +#define WCSTOK wcstok +#endif + /* For Py_GetArgcArgv(); set by main() */ static wchar_t **orig_argv = NULL; static int orig_argc = 0; @@ -170,6 +176,50 @@ pymain_get_env_var(const char *name) } +static int +config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name) +{ + if (Py_IgnoreEnvironmentFlag) { + *dest = NULL; + return 0; + } + +#ifdef MS_WINDOWS + const wchar_t *var = _wgetenv(wname); + if (!var || var[0] == '\0') { + *dest = NULL; + return 0; + } + + wchar_t *copy = _PyMem_RawWcsdup(var); + if (copy == NULL) { + return -1; + } + + *dest = copy; +#else + const char *var = getenv(name); + if (!var || var[0] == '\0') { + *dest = NULL; + return 0; + } + + size_t len; + wchar_t *wvar = Py_DecodeLocale(var, &len); + if (!wvar) { + if (len == (size_t)-2) { + return -2; + } + else { + return -1; + } + } + *dest = wvar; +#endif + return 0; +} + + static void pymain_run_startup(PyCompilerFlags *cf) { @@ -378,18 +428,12 @@ pymain_run_file(FILE *fp, const wchar_t *filename, PyCompilerFlags *p_cf) /* Main program */ -typedef struct { - size_t len; - wchar_t **options; -} _Py_OptList; - typedef struct { wchar_t **argv; - const wchar_t *filename; /* Trailing arg without -c or -m */ - wchar_t *command; /* -c argument */ - const wchar_t *module; /* -m argument */ - _Py_OptList warning_options; /* -W options */ - _Py_OptList env_warning_options; /* PYTHONWARNINGS env var */ + int nwarnoption; /* Number of -W options */ + wchar_t **warnoptions; /* -W options */ + int nenv_warnoption; /* Number of PYTHONWARNINGS options */ + wchar_t **env_warnoptions; /* PYTHONWARNINGS options */ int print_help; /* -h, -? options */ int print_version; /* -V option */ int bytes_warning; /* Py_BytesWarningFlag, -b */ @@ -404,8 +448,6 @@ typedef struct { int use_unbuffered_io; /* Py_UnbufferedStdioFlag, -u, PYTHONUNBUFFERED */ int verbosity; /* Py_VerboseFlag, -v, PYTHONVERBOSE */ int quiet_flag; /* Py_QuietFlag, -q */ - int skip_first_line; /* -x option */ - _Py_OptList xoptions; /* -X options */ const char *check_hash_pycs_mode; /* --check-hash-based-pycs */ #ifdef MS_WINDOWS int legacy_windows_fs_encoding; /* Py_LegacyWindowsFSEncodingFlag, @@ -428,9 +470,12 @@ typedef struct { /* Error message if a function failed */ _PyInitError err; - _Py_CommandLineDetails cmdline; /* non-zero is stdin is a TTY or if -i option is used */ int stdin_is_interactive; + int skip_first_line; /* -x option */ + wchar_t *filename; /* Trailing arg without -c or -m */ + wchar_t *command; /* -c argument */ + wchar_t *module; /* -m argument */ _PyCoreConfig core_config; _PyMainInterpreterConfig config; @@ -438,7 +483,6 @@ typedef struct { PyObject *main_importer_path; } _PyMain; -/* .cmdline is initialized to zeros */ #define _PyMain_INIT \ {.core_config = _PyCoreConfig_INIT, \ .config = _PyMainInterpreterConfig_INIT, \ @@ -449,88 +493,117 @@ typedef struct { /* Non-zero if filename, command (-c) or module (-m) is set on the command line */ #define RUN_CODE(pymain) \ - (pymain->cmdline.command != NULL \ - || pymain->cmdline.filename != NULL \ - || pymain->cmdline.module != NULL) + (pymain->command != NULL || pymain->filename != NULL \ + || pymain->module != NULL) -static void -pymain_optlist_clear(_Py_OptList *list) +static wchar_t* +pymain_wstrdup(_PyMain *pymain, const wchar_t *str) { - for (size_t i=0; i < list->len; i++) { - PyMem_RawFree(list->options[i]); + wchar_t *str2 = _PyMem_RawWcsdup(str); + if (str2 == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return NULL; } - PyMem_RawFree(list->options); - list->len = 0; - list->options = NULL; + return str2; } static void -clear_argv(int argc, wchar_t **argv) +clear_wstrlist(int len, wchar_t **list) { - for (int i=0; i < argc; i++) { - PyMem_RawFree(argv[i]); + for (int i=0; i < len; i++) { + PyMem_RawFree(list[i]); } - PyMem_RawFree(argv); + PyMem_RawFree(list); } static int -pymain_init_cmdline_argv(_PyMain *pymain) +pymain_init_cmdline_argv(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - assert(pymain->cmdline.argv == NULL); + assert(cmdline->argv == NULL); - if (!pymain->use_bytes_argv) { - pymain->cmdline.argv = pymain->wchar_argv; - return 0; - } + if (pymain->use_bytes_argv) { + /* +1 for a the NULL terminator */ + size_t size = sizeof(wchar_t*) * (pymain->argc + 1); + wchar_t** argv = (wchar_t **)PyMem_RawMalloc(size); + if (argv == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } - /* +1 for a the NULL terminator */ - size_t size = sizeof(wchar_t*) * (pymain->argc + 1); - wchar_t** argv = (wchar_t **)PyMem_RawMalloc(size); - if (argv == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + for (int i = 0; i < pymain->argc; i++) { + size_t len; + wchar_t *arg = Py_DecodeLocale(pymain->bytes_argv[i], &len); + if (arg == NULL) { + clear_wstrlist(i, argv); + pymain->err = DECODE_LOCALE_ERR("command line arguments", + (Py_ssize_t)len); + return -1; + } + argv[i] = arg; + } + argv[pymain->argc] = NULL; + + cmdline->argv = argv; + } + else { + cmdline->argv = pymain->wchar_argv; } - for (int i = 0; i < pymain->argc; i++) { - size_t len; - wchar_t *arg = Py_DecodeLocale(pymain->bytes_argv[i], &len); - if (arg == NULL) { - clear_argv(i, argv); - pymain->err = DECODE_LOCALE_ERR("command line arguments", - (Py_ssize_t)len); - return -1; - } - argv[i] = arg; + wchar_t *program; + if (pymain->argc >= 1 && cmdline->argv != NULL) { + program = cmdline->argv[0]; + } + else { + program = L""; + } + pymain->core_config.program = pymain_wstrdup(pymain, program); + if (pymain->core_config.program == NULL) { + return -1; } - argv[pymain->argc] = NULL; - pymain->cmdline.argv = argv; return 0; } static void -pymain_clear_cmdline(_PyMain *pymain) +pymain_clear_cmdline(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - /* Clear orig_argv: pymain_init_python_core() uses a borrowed pointer - to pymain->argv */ - orig_argc = 0; - orig_argv = NULL; + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + clear_wstrlist(cmdline->nwarnoption, cmdline->warnoptions); + cmdline->nwarnoption = 0; + cmdline->warnoptions = NULL; - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - pymain_optlist_clear(&cmdline->warning_options); - pymain_optlist_clear(&cmdline->xoptions); - PyMem_RawFree(cmdline->command); - cmdline->command = NULL; - pymain_optlist_clear(&cmdline->env_warning_options); + clear_wstrlist(cmdline->nenv_warnoption, cmdline->env_warnoptions); + cmdline->nenv_warnoption = 0; + cmdline->env_warnoptions = NULL; if (pymain->use_bytes_argv && cmdline->argv != NULL) { - clear_argv(pymain->argc, cmdline->argv); + clear_wstrlist(pymain->argc, cmdline->argv); } cmdline->argv = NULL; + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + + +static void +pymain_clear_pymain(_PyMain *pymain) +{ +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(pymain->filename); + CLEAR(pymain->command); + CLEAR(pymain->module); +#undef CLEAR } static void @@ -586,7 +659,11 @@ pymain_free_raw(_PyMain *pymain) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); _PyCoreConfig_Clear(&pymain->core_config); - pymain_clear_cmdline(pymain); + pymain_clear_pymain(pymain); + + clear_wstrlist(orig_argc, orig_argv); + orig_argc = 0; + orig_argv = NULL; PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } @@ -625,36 +702,24 @@ pymain_run_main_from_importer(_PyMain *pymain) } -static wchar_t* -pymain_wstrdup(_PyMain *pymain, const wchar_t *str) -{ - wchar_t *str2 = _PyMem_RawWcsdup(str); - if (str2 == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); - return NULL; - } - return str2; -} - - static int -pymain_optlist_append(_PyMain *pymain, _Py_OptList *list, const wchar_t *str) +pymain_wstrlist_append(_PyMain *pymain, int *len, wchar_t ***list, const wchar_t *str) { wchar_t *str2 = pymain_wstrdup(pymain, str); if (str2 == NULL) { return -1; } - size_t size = (list->len + 1) * sizeof(list[0]); - wchar_t **options2 = (wchar_t **)PyMem_RawRealloc(list->options, size); - if (options2 == NULL) { + size_t size = (*len + 1) * sizeof(list[0]); + wchar_t **list2 = (wchar_t **)PyMem_RawRealloc(*list, size); + if (list2 == NULL) { PyMem_RawFree(str2); pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - options2[list->len] = str2; - list->options = options2; - list->len++; + list2[*len] = str2; + *list = list2; + (*len)++; return 0; } @@ -664,10 +729,8 @@ pymain_optlist_append(_PyMain *pymain, _Py_OptList *list, const wchar_t *str) Return 1 if parsing failed. Set pymain->err and return -1 on other errors. */ static int -pymain_parse_cmdline_impl(_PyMain *pymain) +pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - _PyOS_ResetGetOpt(); do { int longindex = -1; @@ -690,7 +753,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain) memcpy(command, _PyOS_optarg, len * sizeof(wchar_t)); command[len - 2] = '\n'; command[len - 1] = 0; - cmdline->command = command; + pymain->command = command; break; } @@ -698,7 +761,10 @@ pymain_parse_cmdline_impl(_PyMain *pymain) /* -m is the last option; following arguments that look like options are left for the module to interpret. */ - cmdline->module = _PyOS_optarg; + pymain->module = pymain_wstrdup(pymain, _PyOS_optarg); + if (pymain->module == NULL) { + return -1; + } break; } @@ -773,7 +839,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain) break; case 'x': - cmdline->skip_first_line = 1; + pymain->skip_first_line = 1; break; case 'h': @@ -786,15 +852,19 @@ pymain_parse_cmdline_impl(_PyMain *pymain) break; case 'W': - if (pymain_optlist_append(pymain, &cmdline->warning_options, - _PyOS_optarg) < 0) { + if (pymain_wstrlist_append(pymain, + &cmdline->nwarnoption, + &cmdline->warnoptions, + _PyOS_optarg) < 0) { return -1; } break; case 'X': - if (pymain_optlist_append(pymain, &cmdline->xoptions, - _PyOS_optarg) < 0) { + if (pymain_wstrlist_append(pymain, + &pymain->core_config.nxoption, + &pymain->core_config.xoptions, + _PyOS_optarg) < 0) { return -1; } break; @@ -815,15 +885,18 @@ pymain_parse_cmdline_impl(_PyMain *pymain) } } while (1); - if (cmdline->command == NULL && cmdline->module == NULL + if (pymain->command == NULL && pymain->module == NULL && _PyOS_optind < pymain->argc && wcscmp(cmdline->argv[_PyOS_optind], L"-") != 0) { - cmdline->filename = cmdline->argv[_PyOS_optind]; + pymain->filename = pymain_wstrdup(pymain, cmdline->argv[_PyOS_optind]); + if (pymain->filename == NULL) { + return -1; + } } /* -c and -m options are exclusive */ - assert(!(cmdline->command != NULL && cmdline->module != NULL)); + assert(!(pymain->command != NULL && pymain->module != NULL)); return 0; } @@ -863,14 +936,15 @@ pymain_add_xoption(PyObject *opts, const wchar_t *s) static int pymain_init_xoptions_dict(_PyMain *pymain) { - _Py_OptList *options = &pymain->cmdline.xoptions; + int nxoption = pymain->core_config.nxoption; + wchar_t **xoptions = pymain->core_config.xoptions; PyObject *dict = PyDict_New(); if (dict == NULL) { return -1; } - for (size_t i=0; i < options->len; i++) { - wchar_t *option = options->options[i]; + for (int i=0; i < nxoption; i++) { + wchar_t *option = xoptions[i]; if (pymain_add_xoption(dict, option) < 0) { Py_DECREF(dict); return -1; @@ -883,104 +957,103 @@ pymain_init_xoptions_dict(_PyMain *pymain) static int -pymain_add_warnings_optlist(PyObject *warnoptions, _Py_OptList *warnings) -{ - for (size_t i = 0; i < warnings->len; i++) { - PyObject *option = PyUnicode_FromWideChar(warnings->options[i], -1); - if (option == NULL) { +pymain_add_warnings_optlist(_PyMain *pymain, int len, wchar_t **options) +{ + for (int i = 0; i < len; i++) { + if (pymain_wstrlist_append(pymain, + &pymain->core_config.nwarnoption, + &pymain->core_config.warnoptions, + options[i]) < 0) + { return -1; } - if (PyList_Append(warnoptions, option)) { - Py_DECREF(option); - return -1; - } - Py_DECREF(option); } return 0; } static int -pymain_add_warning_dev_mode(PyObject *warnoptions, _PyCoreConfig *core_config) +pymain_init_warnoptions(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - if (core_config->dev_mode) { - PyObject *option = PyUnicode_FromString("default"); - if (option == NULL) { - return -1; - } - if (PyList_Append(warnoptions, option)) { - Py_DECREF(option); + /* The priority order for warnings configuration is (highest precedence + * first): + * + * - the BytesWarning filter, if needed ('-b', '-bb') + * - any '-W' command line options; then + * - the 'PYTHONWARNINGS' environment variable; then + * - the dev mode filter ('-X dev', 'PYTHONDEVMODE'); then + * - any implicit filters added by _warnings.c/warnings.py + * + * All settings except the last are passed to the warnings module via + * the `sys.warnoptions` list. Since the warnings module works on the basis + * of "the most recently added filter will be checked first", we add + * the lowest precedence entries first so that later entries override them. + */ + + if (pymain->core_config.dev_mode) { + if (pymain_wstrlist_append(pymain, + &pymain->core_config.nwarnoption, + &pymain->core_config.warnoptions, + L"default") < 0) + { return -1; } - Py_DECREF(option); } - return 0; -} + if (pymain_add_warnings_optlist(pymain, cmdline->nenv_warnoption, cmdline->env_warnoptions) < 0) { + return -1; + } + + if (pymain_add_warnings_optlist(pymain, cmdline->nwarnoption, cmdline->warnoptions) < 0) { + return -1; + } -static int -pymain_add_warning_bytes_flag(PyObject *warnoptions, int bytes_warning_flag) -{ /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c * don't even try to emit a warning, so we skip setting the filter in that * case. */ - if (!bytes_warning_flag) { - return 0; - } - - const char *filter = (bytes_warning_flag > 1) ? "error::BytesWarning": - "default::BytesWarning"; - PyObject *option = PyUnicode_FromString(filter); - if (option == NULL) { - return -1; - } - if (PyList_Append(warnoptions, option)) { - Py_DECREF(option); - return -1; + if (cmdline->bytes_warning) { + wchar_t *filter; + if (cmdline->bytes_warning> 1) { + filter = L"error::BytesWarning"; + } + else { + filter = L"default::BytesWarning"; + } + if (pymain_wstrlist_append(pymain, + &pymain->core_config.nwarnoption, + &pymain->core_config.warnoptions, + filter) < 0) + { + return -1; + } } - Py_DECREF(option); return 0; } static int -pymain_init_warnoptions(_PyMain *pymain) +config_init_warnoptions(_PyMainInterpreterConfig *config, + const _PyCoreConfig *core_config) { PyObject *warnoptions = PyList_New(0); if (warnoptions == NULL) { return -1; } - /* The priority order for warnings configuration is (highest precedence - * first): - * - * - the BytesWarning filter, if needed ('-b', '-bb') - * - any '-W' command line options; then - * - the 'PYTHONWARNINGS' environment variable; then - * - the dev mode filter ('-X dev', 'PYTHONDEVMODE'); then - * - any implicit filters added by _warnings.c/warnings.py - * - * All settings except the last are passed to the warnings module via - * the `sys.warnoptions` list. Since the warnings module works on the basis - * of "the most recently added filter will be checked first", we add - * the lowest precedence entries first so that later entries override them. - */ - - if (pymain_add_warning_dev_mode(warnoptions, &pymain->core_config) < 0) { - goto error; - } - if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.env_warning_options) < 0) { - goto error; - } - if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.warning_options) < 0) { - goto error; - } - if (pymain_add_warning_bytes_flag(warnoptions, pymain->cmdline.bytes_warning) < 0) { - goto error; + for (int i = 0; i < core_config->nwarnoption; i++) { + PyObject *option = PyUnicode_FromWideChar(core_config->warnoptions[i], -1); + if (option == NULL) { + goto error; + } + if (PyList_Append(warnoptions, option)) { + Py_DECREF(option); + goto error; + } + Py_DECREF(option); } - pymain->config.warnoptions = warnoptions; + config->warnoptions = warnoptions; return 0; error: @@ -993,68 +1066,39 @@ pymain_init_warnoptions(_PyMain *pymain) Return 0 on success. Set pymain->err and return -1 on error. */ static int -pymain_warnings_envvar(_PyMain *pymain) +pymain_warnings_envvar(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { if (Py_IgnoreEnvironmentFlag) { return 0; } -#ifdef MS_WINDOWS - const wchar_t *wp; - - if ((wp = _wgetenv(L"PYTHONWARNINGS")) && *wp != L'\0') { - wchar_t *warning, *context = NULL; - - wchar_t *buf = pymain_wstrdup(pymain, wp); - if (buf == NULL) { - return -1; - } - for (warning = wcstok_s(buf, L",", &context); - warning != NULL; - warning = wcstok_s(NULL, L",", &context)) { + wchar_t *env; + int res = config_get_env_var_dup(&env, L"PYTHONWARNINGS", "PYTHONWARNINGS"); + if (res < 0) { + pymain->err = DECODE_LOCALE_ERR("PYTHONWARNINGS", res); + return -1; + } - if (pymain_optlist_append(pymain, &pymain->cmdline.env_warning_options, - warning) < 0) { - PyMem_RawFree(buf); - return -1; - } - } - PyMem_RawFree(buf); + if (env == NULL) { + return 0; } -#else - const char *p = pymain_get_env_var("PYTHONWARNINGS"); - if (p != NULL) { - char *buf, *oldloc; - /* settle for strtok here as there's no one standard - C89 wcstok */ - buf = (char *)PyMem_RawMalloc(strlen(p) + 1); - if (buf == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); + + wchar_t *warning, *context = NULL; + for (warning = WCSTOK(env, L",", &context); + warning != NULL; + warning = WCSTOK(NULL, L",", &context)) + { + if (pymain_wstrlist_append(pymain, + &cmdline->nenv_warnoption, + &cmdline->env_warnoptions, + warning) < 0) + { + PyMem_RawFree(env); return -1; } - strcpy(buf, p); - oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); - setlocale(LC_ALL, ""); - for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) { - size_t len; - wchar_t *warning = Py_DecodeLocale(p, &len); - if (warning == NULL) { - SET_DECODE_ERROR("PYTHONWARNINGS environment variable", len); - return -1; - } - if (pymain_optlist_append(pymain, &pymain->cmdline.env_warning_options, - warning) < 0) { - PyMem_RawFree(warning); - return -1; - } - PyMem_RawFree(warning); - } - setlocale(LC_ALL, oldloc); - PyMem_RawFree(oldloc); - PyMem_RawFree(buf); } -#endif + PyMem_RawFree(env); return 0; } @@ -1102,7 +1146,7 @@ pymain_init_stdio(_PyMain *pymain) /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ environment variables on macOS if available. */ static _PyInitError -config_get_program_name(_PyCoreConfig *config) +config_init_program_name(_PyCoreConfig *config) { assert(config->program_name == NULL); @@ -1113,6 +1157,7 @@ config_get_program_name(_PyCoreConfig *config) if (config->program_name == NULL) { return _Py_INIT_NO_MEMORY(); } + return _Py_INIT_OK(); } #ifdef __APPLE__ @@ -1134,6 +1179,7 @@ config_get_program_name(_PyCoreConfig *config) "variable", (Py_ssize_t)len); } config->program_name = program_name; + return _Py_INIT_OK(); } #ifdef WITH_NEXT_FRAMEWORK else { @@ -1149,28 +1195,32 @@ config_get_program_name(_PyCoreConfig *config) "variable", (Py_ssize_t)len); } config->program_name = program_name; + return _Py_INIT_OK(); } } #endif /* WITH_NEXT_FRAMEWORK */ #endif /* __APPLE__ */ - return _Py_INIT_OK(); -} - - -/* If config_get_program_name() found no program name: use argv[0] by default. - Return 0 on success. Set pymain->err and return -1 on error. */ -static int -pymain_get_program_name(_PyMain *pymain) -{ - if (pymain->core_config.program_name == NULL) { - /* Use argv[0] by default */ - pymain->core_config.program_name = pymain_wstrdup(pymain, pymain->cmdline.argv[0]); - if (pymain->core_config.program_name == NULL) { - return -1; + /* Use argv[0] by default, if available */ + if (config->program != NULL) { + config->program_name = _PyMem_RawWcsdup(config->program); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); } + return _Py_INIT_OK(); } - return 0; + + /* Last fall back: hardcoded string */ +#ifdef MS_WINDOWS + const wchar_t *default_program_name = L"python"; +#else + const wchar_t *default_program_name = L"python3"; +#endif + config->program_name = _PyMem_RawWcsdup(default_program_name); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); } @@ -1193,28 +1243,26 @@ pymain_header(_PyMain *pymain) static wchar_t** -copy_argv(int argc, wchar_t **argv) +copy_wstrlist(int len, wchar_t **list) { - assert(argc >= 0 && argv != NULL); - size_t size = argc * sizeof(argv[0]); - wchar_t **argv_copy = PyMem_RawMalloc(size); - for (int i=0; i < argc; i++) { - wchar_t* arg = _PyMem_RawWcsdup(argv[i]); + assert((len > 0 && list != NULL) || len == 0); + size_t size = len * sizeof(list[0]); + wchar_t **list_copy = PyMem_RawMalloc(size); + for (int i=0; i < len; i++) { + wchar_t* arg = _PyMem_RawWcsdup(list[i]); if (arg == NULL) { - clear_argv(i, argv); + clear_wstrlist(i, list); return NULL; } - argv_copy[i] = arg; + list_copy[i] = arg; } - return argv_copy; + return list_copy; } static int -pymain_init_core_argv(_PyMain *pymain) +pymain_init_core_argv(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - /* Copy argv to be able to modify it (to force -c/-m) */ int argc = pymain->argc - _PyOS_optind; wchar_t **argv; @@ -1223,10 +1271,10 @@ pymain_init_core_argv(_PyMain *pymain) /* Ensure at least one (empty) argument is seen */ static wchar_t *empty_argv[1] = {L""}; argc = 1; - argv = copy_argv(1, empty_argv); + argv = copy_wstrlist(1, empty_argv); } else { - argv = copy_argv(argc, &cmdline->argv[_PyOS_optind]); + argv = copy_wstrlist(argc, &cmdline->argv[_PyOS_optind]); } if (argv == NULL) { @@ -1235,21 +1283,23 @@ pymain_init_core_argv(_PyMain *pymain) } wchar_t *arg0 = NULL; - if (cmdline->command != NULL) { + if (pymain->command != NULL) { /* Force sys.argv[0] = '-c' */ arg0 = L"-c"; } - else if (cmdline->module != NULL) { + else if (pymain->module != NULL) { /* Force sys.argv[0] = '-m'*/ arg0 = L"-m"; } if (arg0 != NULL) { arg0 = _PyMem_RawWcsdup(arg0); if (arg0 == NULL) { - clear_argv(argc, argv); + clear_wstrlist(argc, argv); pymain->err = _Py_INIT_NO_MEMORY(); return -1; } + + assert(argc >= 1); PyMem_RawFree(argv[0]); argv[0] = arg0; } @@ -1338,10 +1388,8 @@ pymain_update_sys_path(_PyMain *pymain, PyObject *path0) /* Get Py_xxx global configuration variables */ static void -pymain_get_global_config(_PyMain *pymain) +pymain_get_global_config(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - cmdline->bytes_warning = Py_BytesWarningFlag; cmdline->debug = Py_DebugFlag; cmdline->inspect = Py_InspectFlag; @@ -1367,10 +1415,8 @@ pymain_get_global_config(_PyMain *pymain) /* Set Py_xxx global configuration variables */ static void -pymain_set_global_config(_PyMain *pymain) +pymain_set_global_config(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - Py_BytesWarningFlag = cmdline->bytes_warning; Py_DebugFlag = cmdline->debug; Py_InspectFlag = cmdline->inspect; @@ -1424,27 +1470,26 @@ pymain_import_readline(_PyMain *pymain) static FILE* pymain_open_filename(_PyMain *pymain) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; FILE* fp; - fp = _Py_wfopen(cmdline->filename, L"r"); + fp = _Py_wfopen(pymain->filename, L"r"); if (fp == NULL) { char *cfilename_buffer; const char *cfilename; int err = errno; - cfilename_buffer = Py_EncodeLocale(cmdline->filename, NULL); + cfilename_buffer = Py_EncodeLocale(pymain->filename, NULL); if (cfilename_buffer != NULL) cfilename = cfilename_buffer; else cfilename = ""; fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n", - cmdline->argv[0], cfilename, err, strerror(err)); + pymain->core_config.program, cfilename, err, strerror(err)); PyMem_Free(cfilename_buffer); pymain->status = 2; return NULL; } - if (cmdline->skip_first_line) { + if (pymain->skip_first_line) { int ch; /* Push back first newline so line numbers remain the same */ @@ -1461,7 +1506,7 @@ pymain_open_filename(_PyMain *pymain) S_ISDIR(sb.st_mode)) { fprintf(stderr, "%ls: '%ls' is a directory, cannot continue\n", - cmdline->argv[0], cmdline->filename); + pymain->core_config.program, pymain->filename); fclose(fp); pymain->status = 1; return NULL; @@ -1474,9 +1519,7 @@ pymain_open_filename(_PyMain *pymain) static void pymain_run_filename(_PyMain *pymain, PyCompilerFlags *cf) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - - if (cmdline->filename == NULL && pymain->stdin_is_interactive) { + if (pymain->filename == NULL && pymain->stdin_is_interactive) { Py_InspectFlag = 0; /* do exit on SystemExit */ pymain_run_startup(cf); pymain_run_interactive_hook(); @@ -1488,7 +1531,7 @@ pymain_run_filename(_PyMain *pymain, PyCompilerFlags *cf) } FILE *fp; - if (cmdline->filename != NULL) { + if (pymain->filename != NULL) { fp = pymain_open_filename(pymain); if (fp == NULL) { return; @@ -1498,7 +1541,7 @@ pymain_run_filename(_PyMain *pymain, PyCompilerFlags *cf) fp = stdin; } - pymain->status = pymain_run_file(fp, cmdline->filename, cf); + pymain->status = pymain_run_file(fp, pymain->filename, cf); } @@ -1530,19 +1573,19 @@ pymain_repl(_PyMain *pymain, PyCompilerFlags *cf) Return 0 on success. Set pymain->err and return -1 on failure. */ static int -pymain_parse_cmdline(_PyMain *pymain) +pymain_parse_cmdline(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - int res = pymain_parse_cmdline_impl(pymain); + int res = pymain_parse_cmdline_impl(pymain, cmdline); if (res < 0) { return -1; } if (res) { - pymain_usage(1, pymain->cmdline.argv[0]); + pymain_usage(1, pymain->core_config.program); pymain->status = 2; return 1; } - if (pymain->cmdline.command != NULL || pymain->cmdline.module != NULL) { + if (pymain->command != NULL || pymain->module != NULL) { /* Backup _PyOS_optind */ _PyOS_optind--; } @@ -1554,9 +1597,10 @@ pymain_parse_cmdline(_PyMain *pymain) static const wchar_t* pymain_get_xoption(_PyMain *pymain, wchar_t *name) { - _Py_OptList *list = &pymain->cmdline.xoptions; - for (size_t i=0; i < list->len; i++) { - wchar_t *option = list->options[i]; + int nxoption = pymain->core_config.nxoption; + wchar_t **xoptions = pymain->core_config.xoptions; + for (int i=0; i < nxoption; i++) { + wchar_t *option = xoptions[i]; size_t len; wchar_t *sep = wcschr(option, L'='); if (sep != NULL) { @@ -1658,7 +1702,7 @@ pymain_init_tracemalloc(_PyMain *pymain) static void -pymain_set_flag_from_env(int *flag, const char *name) +pymain_get_env_flag(int *flag, const char *name) { const char *var = pymain_get_env_var(name); if (!var) { @@ -1676,78 +1720,33 @@ pymain_set_flag_from_env(int *flag, const char *name) static void -pymain_set_flags_from_env(_PyMain *pymain) +pymain_get_env_flags(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - _Py_CommandLineDetails *cmdline = &pymain->cmdline; - pymain_set_flag_from_env(&cmdline->debug, + pymain_get_env_flag(&cmdline->debug, "PYTHONDEBUG"); - pymain_set_flag_from_env(&cmdline->verbosity, + pymain_get_env_flag(&cmdline->verbosity, "PYTHONVERBOSE"); - pymain_set_flag_from_env(&cmdline->optimization_level, + pymain_get_env_flag(&cmdline->optimization_level, "PYTHONOPTIMIZE"); - pymain_set_flag_from_env(&cmdline->inspect, + pymain_get_env_flag(&cmdline->inspect, "PYTHONINSPECT"); - pymain_set_flag_from_env(&cmdline->dont_write_bytecode, + pymain_get_env_flag(&cmdline->dont_write_bytecode, "PYTHONDONTWRITEBYTECODE"); - pymain_set_flag_from_env(&cmdline->no_user_site_directory, + pymain_get_env_flag(&cmdline->no_user_site_directory, "PYTHONNOUSERSITE"); - pymain_set_flag_from_env(&cmdline->use_unbuffered_io, + pymain_get_env_flag(&cmdline->use_unbuffered_io, "PYTHONUNBUFFERED"); #ifdef MS_WINDOWS - pymain_set_flag_from_env(&cmdline->legacy_windows_fs_encoding, + pymain_get_env_flag(&cmdline->legacy_windows_fs_encoding, "PYTHONLEGACYWINDOWSFSENCODING"); - pymain_set_flag_from_env(&cmdline->legacy_windows_stdio, + pymain_get_env_flag(&cmdline->legacy_windows_stdio, "PYTHONLEGACYWINDOWSSTDIO"); #endif } -static int -config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name) -{ - if (Py_IgnoreEnvironmentFlag) { - *dest = NULL; - return 0; - } - -#ifdef MS_WINDOWS - const wchar_t *var = _wgetenv(wname); - if (!var || var[0] == '\0') { - *dest = NULL; - return 0; - } - - wchar_t *copy = _PyMem_RawWcsdup(var); - if (copy == NULL) { - return -1; - } - - *dest = copy; -#else - const char *var = getenv(name); - if (!var || var[0] == '\0') { - *dest = NULL; - return 0; - } - - size_t len; - wchar_t *wvar = Py_DecodeLocale(var, &len); - if (!wvar) { - if (len == (size_t)-2) { - return -2; - } - else { - return -1; - } - } - *dest = wvar; -#endif - return 0; -} - - static _PyInitError -config_init_pythonpath(_PyCoreConfig *config) +config_init_module_search_path_env(_PyCoreConfig *config) { wchar_t *path; int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH"); @@ -1801,40 +1800,13 @@ config_init_hash_seed(_PyCoreConfig *config) } -_PyInitError -_PyCoreConfig_ReadEnv(_PyCoreConfig *config) -{ - _PyInitError err = config_init_home(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - err = config_init_pythonpath(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - err = config_get_program_name(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - err = config_init_hash_seed(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - return _Py_INIT_OK(); -} - - static int -pymain_init_utf8_mode(_PyMain *pymain) +pymain_init_utf8_mode(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { _PyCoreConfig *core_config = &pymain->core_config; #ifdef MS_WINDOWS - if (pymain->cmdline.legacy_windows_fs_encoding) { + if (cmdline->legacy_windows_fs_encoding) { core_config->utf8_mode = 0; return 0; } @@ -1882,23 +1854,14 @@ pymain_init_utf8_mode(_PyMain *pymain) static int -pymain_parse_envvars(_PyMain *pymain) +pymain_parse_envvars(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { _PyCoreConfig *core_config = &pymain->core_config; /* Get environment variables */ - pymain_set_flags_from_env(pymain); - - if (pymain_warnings_envvar(pymain) < 0) { - return -1; - } + pymain_get_env_flags(pymain, cmdline); - _PyInitError err = _PyCoreConfig_ReadEnv(&pymain->core_config); - if (_Py_INIT_FAILED(pymain->err)) { - pymain->err = err; - return -1; - } - if (pymain_get_program_name(pymain) < 0) { + if (pymain_warnings_envvar(pymain, cmdline) < 0) { return -1; } @@ -1951,10 +1914,6 @@ pymain_parse_envvars(_PyMain *pymain) } } - if (pymain_init_utf8_mode(pymain) < 0) { - return -1; - } - return 0; } @@ -1966,21 +1925,25 @@ pymain_parse_envvars(_PyMain *pymain) Return 1 if Python is done and must exit. Set pymain->err and return -1 on error. */ static int -pymain_read_conf_impl(_PyMain *pymain) +pymain_read_conf_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { - int res = pymain_parse_cmdline(pymain); + int res = pymain_parse_cmdline(pymain, cmdline); if (res != 0) { return res; } - if (pymain_init_core_argv(pymain) < 0) { + if (pymain_init_core_argv(pymain, cmdline) < 0) { return -1; } /* Set Py_IgnoreEnvironmentFlag for Py_GETENV() */ Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; - if (pymain_parse_envvars(pymain) < 0) { + if (pymain_parse_envvars(pymain, cmdline) < 0) { + return -1; + } + + if (pymain_init_utf8_mode(pymain, cmdline) < 0) { return -1; } @@ -1996,7 +1959,7 @@ pymain_read_conf_impl(_PyMain *pymain) /* Read the configuration, but initialize also the LC_CTYPE locale: enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */ static int -pymain_read_conf(_PyMain *pymain) +pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { int res = -1; @@ -2030,11 +1993,11 @@ pymain_read_conf(_PyMain *pymain) goto done; } - if (pymain_init_cmdline_argv(pymain) < 0) { + if (pymain_init_cmdline_argv(pymain, cmdline) < 0) { goto done; } - res = pymain_read_conf_impl(pymain); + res = pymain_read_conf_impl(pymain, cmdline); if (res != 0) { goto done; } @@ -2077,8 +2040,8 @@ pymain_read_conf(_PyMain *pymain) Py_UTF8Mode = pymain->core_config.utf8_mode; Py_IgnoreEnvironmentFlag = init_ignore_env; _PyCoreConfig_Clear(&pymain->core_config); - pymain_clear_cmdline(pymain); - pymain_get_global_config(pymain); + pymain_clear_cmdline(pymain, cmdline); + pymain_get_global_config(pymain, cmdline); /* The encoding changed: read again the configuration with the new encoding */ @@ -2111,16 +2074,24 @@ pymain_read_conf(_PyMain *pymain) _PyInitError _PyCoreConfig_Read(_PyCoreConfig *config) { - if (config->program_name == NULL) { -#ifdef MS_WINDOWS - const wchar_t *program_name = L"python"; -#else - const wchar_t *program_name = L"python3"; -#endif - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); - } + _PyInitError err = config_init_home(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + err = config_init_module_search_path_env(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + err = config_init_program_name(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + err = config_init_hash_seed(config); + if (_Py_INIT_FAILED(err)) { + return err; } if (config->utf8_mode < 0 || config->coerce_c_locale < 0) { @@ -2157,13 +2128,22 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) CLEAR(config->module_search_path_env); CLEAR(config->home); CLEAR(config->program_name); -#undef CLEAR + CLEAR(config->program); if (config->argc >= 0) { - clear_argv(config->argc, config->argv); + clear_wstrlist(config->argc, config->argv); config->argc = -1; config->argv = NULL; } + + clear_wstrlist(config->nwarnoption, config->warnoptions); + config->nwarnoption = 0; + config->warnoptions = NULL; + + clear_wstrlist(config->nxoption, config->xoptions); + config->nxoption = 0; + config->xoptions = NULL; +#undef CLEAR } @@ -2201,9 +2181,10 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_STR_ATTR(module_search_path_env); COPY_STR_ATTR(home); COPY_STR_ATTR(program_name); + COPY_STR_ATTR(program); if (config2->argc >= 0) { - wchar_t **argv = copy_argv(config2->argc, config2->argv); + wchar_t **argv = copy_wstrlist(config2->argc, config2->argv); if (argv == NULL) { return -1; } @@ -2211,6 +2192,22 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) } COPY_ATTR(argc); + if (config2->nwarnoption > 0) { + config->warnoptions = copy_wstrlist(config2->nwarnoption, config2->warnoptions); + if (config->warnoptions == NULL) { + return -1; + } + } + COPY_ATTR(nwarnoption); + + if (config2->nxoption > 0) { + config->xoptions = copy_wstrlist(config2->nxoption, config2->xoptions); + if (config->xoptions == NULL) { + return -1; + } + } + COPY_ATTR(nxoption); + #undef COPY_ATTR #undef COPY_STR_ATTR return 0; @@ -2337,6 +2334,10 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, const _PyCoreCon return _Py_INIT_ERR("failed to create sys.argv"); } + if (config_init_warnoptions(config, core_config) < 0) { + return _Py_INIT_NO_MEMORY(); + } + /* Signal handlers are installed by default */ if (config->install_signal_handlers < 0) { config->install_signal_handlers = 1; @@ -2390,8 +2391,6 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, const _PyCoreCon static int pymain_init_python_core(_PyMain *pymain) { - pymain_set_global_config(pymain); - pymain_init_stdio(pymain); pymain->err = _Py_InitializeCore(&pymain->core_config); @@ -2409,10 +2408,6 @@ pymain_init_python_main(_PyMain *pymain) pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - if (pymain_init_warnoptions(pymain)) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; - } _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config, &pymain->core_config); @@ -2427,12 +2422,12 @@ pymain_init_python_main(_PyMain *pymain) return -1; } - if (pymain->cmdline.filename != NULL) { + if (pymain->filename != NULL) { /* If filename is a package (ex: directory or ZIP file) which contains __main__.py, main_importer_path is set to filename and will be prepended to sys.path by pymain_run_main_from_importer(). Otherwise, main_importer_path is set to NULL. */ - pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename); + pymain->main_importer_path = pymain_get_importer(pymain->filename); } PyObject *path0; @@ -2458,16 +2453,15 @@ static void pymain_run_python(_PyMain *pymain) { PyCompilerFlags cf = {.cf_flags = 0}; - _Py_CommandLineDetails *cmdline = &pymain->cmdline; pymain_header(pymain); pymain_import_readline(pymain); - if (cmdline->command) { - pymain->status = pymain_run_command(cmdline->command, &cf); + if (pymain->command) { + pymain->status = pymain_run_command(pymain->command, &cf); } - else if (cmdline->module) { - pymain->status = (pymain_run_module(cmdline->module, 1) != 0); + else if (pymain->module) { + pymain->status = (pymain_run_module(pymain->module, 1) != 0); } else { pymain_run_filename(pymain, &cf); @@ -2479,8 +2473,6 @@ pymain_run_python(_PyMain *pymain) static void pymain_init(_PyMain *pymain) { - memset(&pymain->cmdline, 0, sizeof(pymain->cmdline)); - /* 754 requires that FP exceptions run in "no stop" mode by default, * and until C vendors implement C99's ways to control FP exceptions, * Python requires non-stop mode. Alas, some platforms enable FP @@ -2492,20 +2484,18 @@ pymain_init(_PyMain *pymain) pymain->core_config._disable_importlib = 0; pymain->config.install_signal_handlers = 1; - - pymain_get_global_config(pymain); } static int -pymain_init_cmdline(_PyMain *pymain) +pymain_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { pymain->err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(pymain->err)) { return -1; } - int res = pymain_read_conf(pymain); + int res = pymain_read_conf(pymain, cmdline); if (res < 0) { return -1; } @@ -2514,9 +2504,8 @@ pymain_init_cmdline(_PyMain *pymain) return 1; } - _Py_CommandLineDetails *cmdline = &pymain->cmdline; if (cmdline->print_help) { - pymain_usage(0, cmdline->argv[0]); + pymain_usage(0, pymain->core_config.program); return 1; } @@ -2527,18 +2516,54 @@ pymain_init_cmdline(_PyMain *pymain) } /* For Py_GetArgcArgv(). Cleared by pymain_free(). */ + orig_argv = copy_wstrlist(pymain->argc, cmdline->argv); + if (orig_argv == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; + } orig_argc = pymain->argc; - orig_argv = cmdline->argv; + + if (pymain_init_warnoptions(pymain, cmdline) < 0) { + return -1; + } return 0; } +/* Read the configuration into _PyCoreConfig and _PyMain, initialize the + LC_CTYPE locale and Py_DecodeLocale(). + + Configuration: + + * Command line arguments + * Environment variables + * Py_xxx global configuration variables + + _Py_CommandLineDetails is a temporary structure used to prioritize these + variables. */ +static int +pymain_cmdline(_PyMain *pymain) +{ + _Py_CommandLineDetails cmdline; + memset(&cmdline, 0, sizeof(cmdline)); + + pymain_get_global_config(pymain, &cmdline); + + int res = pymain_cmdline_impl(pymain, &cmdline); + + pymain_set_global_config(pymain, &cmdline); + + pymain_clear_cmdline(pymain, &cmdline); + return res; +} + + static int pymain_main(_PyMain *pymain) { pymain_init(pymain); - int res = pymain_init_cmdline(pymain); + int res = pymain_cmdline(pymain); if (res < 0) { _Py_FatalInitError(pymain->err); } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 748084ba448..acb25b6fa89 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -107,11 +107,6 @@ pathconfig_global_init(void) _PyInitError err; _PyCoreConfig config = _PyCoreConfig_INIT; - err = _PyCoreConfig_ReadEnv(&config); - if (_Py_INIT_FAILED(err)) { - goto error; - } - err = _PyCoreConfig_Read(&config); if (_Py_INIT_FAILED(err)) { goto error; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index d82782623de..79fcb5777e3 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -882,7 +882,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) core_config._disable_importlib = !install_importlib; config.install_signal_handlers = install_sigs; - err = _PyCoreConfig_ReadEnv(&core_config); + err = _PyCoreConfig_Read(&core_config); if (_Py_INIT_FAILED(err)) { goto done; } @@ -2030,7 +2030,7 @@ void _Py_PyAtExit(void (*func)(PyObject *), PyObject *module) { PyThreadState *ts; PyInterpreterState *is; - + ts = PyThreadState_GET(); is = ts->interp; From webhook-mailer at python.org Wed Dec 20 12:21:05 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 20 Dec 2017 17:21:05 -0000 Subject: [Python-checkins] bpo-32385: Clean up the C3 MRO algorithm implementation. (#4942) Message-ID: https://github.com/python/cpython/commit/6b91a5972107ec8dd5334f4f2005626baa2b8847 commit: 6b91a5972107ec8dd5334f4f2005626baa2b8847 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-20T19:21:02+02:00 summary: bpo-32385: Clean up the C3 MRO algorithm implementation. (#4942) Use tuples and raw arrays instead of lists. files: M Objects/typeobject.c diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 849c6dc1929..40c8fadc52e 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1564,12 +1564,13 @@ call_maybe(PyObject *obj, _Py_Identifier *name, */ static int -tail_contains(PyObject *list, int whence, PyObject *o) { +tail_contains(PyObject *tuple, int whence, PyObject *o) +{ Py_ssize_t j, size; - size = PyList_GET_SIZE(list); + size = PyTuple_GET_SIZE(tuple); for (j = whence+1; j < size; j++) { - if (PyList_GET_ITEM(list, j) == o) + if (PyTuple_GET_ITEM(tuple, j) == o) return 1; } return 0; @@ -1593,17 +1594,17 @@ class_name(PyObject *cls) } static int -check_duplicates(PyObject *list) +check_duplicates(PyObject *tuple) { Py_ssize_t i, j, n; /* Let's use a quadratic time algorithm, - assuming that the bases lists is short. + assuming that the bases tuples is short. */ - n = PyList_GET_SIZE(list); + n = PyTuple_GET_SIZE(tuple); for (i = 0; i < n; i++) { - PyObject *o = PyList_GET_ITEM(list, i); + PyObject *o = PyTuple_GET_ITEM(tuple, i); for (j = i + 1; j < n; j++) { - if (PyList_GET_ITEM(list, j) == o) { + if (PyTuple_GET_ITEM(tuple, j) == o) { o = class_name(o); if (o != NULL) { PyErr_Format(PyExc_TypeError, @@ -1631,19 +1632,18 @@ check_duplicates(PyObject *list) */ static void -set_mro_error(PyObject *to_merge, int *remain) +set_mro_error(PyObject **to_merge, Py_ssize_t to_merge_size, int *remain) { - Py_ssize_t i, n, off, to_merge_size; + Py_ssize_t i, n, off; char buf[1000]; PyObject *k, *v; PyObject *set = PyDict_New(); if (!set) return; - to_merge_size = PyList_GET_SIZE(to_merge); for (i = 0; i < to_merge_size; i++) { - PyObject *L = PyList_GET_ITEM(to_merge, i); - if (remain[i] < PyList_GET_SIZE(L)) { - PyObject *c = PyList_GET_ITEM(L, remain[i]); + PyObject *L = to_merge[i]; + if (remain[i] < PyTuple_GET_SIZE(L)) { + PyObject *c = PyTuple_GET_ITEM(L, remain[i]); if (PyDict_SetItem(set, c, Py_None) < 0) { Py_DECREF(set); return; @@ -1676,19 +1676,17 @@ consistent method resolution\norder (MRO) for bases"); } static int -pmerge(PyObject *acc, PyObject* to_merge) +pmerge(PyObject *acc, PyObject **to_merge, Py_ssize_t to_merge_size) { int res = 0; - Py_ssize_t i, j, to_merge_size, empty_cnt; + Py_ssize_t i, j, empty_cnt; int *remain; - to_merge_size = PyList_GET_SIZE(to_merge); - /* remain stores an index into each sublist of to_merge. remain[i] is the index of the next base in to_merge[i] that is not included in acc. */ - remain = (int *)PyMem_MALLOC(SIZEOF_INT*to_merge_size); + remain = PyMem_New(int, to_merge_size); if (remain == NULL) { PyErr_NoMemory(); return -1; @@ -1701,9 +1699,9 @@ pmerge(PyObject *acc, PyObject* to_merge) for (i = 0; i < to_merge_size; i++) { PyObject *candidate; - PyObject *cur_list = PyList_GET_ITEM(to_merge, i); + PyObject *cur_tuple = to_merge[i]; - if (remain[i] >= PyList_GET_SIZE(cur_list)) { + if (remain[i] >= PyTuple_GET_SIZE(cur_tuple)) { empty_cnt++; continue; } @@ -1715,9 +1713,9 @@ pmerge(PyObject *acc, PyObject* to_merge) of the earliest direct superclass of the new class. */ - candidate = PyList_GET_ITEM(cur_list, remain[i]); + candidate = PyTuple_GET_ITEM(cur_tuple, remain[i]); for (j = 0; j < to_merge_size; j++) { - PyObject *j_lst = PyList_GET_ITEM(to_merge, j); + PyObject *j_lst = to_merge[j]; if (tail_contains(j_lst, remain[j], candidate)) goto skip; /* continue outer loop */ } @@ -1726,9 +1724,9 @@ pmerge(PyObject *acc, PyObject* to_merge) goto out; for (j = 0; j < to_merge_size; j++) { - PyObject *j_lst = PyList_GET_ITEM(to_merge, j); - if (remain[j] < PyList_GET_SIZE(j_lst) && - PyList_GET_ITEM(j_lst, remain[j]) == candidate) { + PyObject *j_lst = to_merge[j]; + if (remain[j] < PyTuple_GET_SIZE(j_lst) && + PyTuple_GET_ITEM(j_lst, remain[j]) == candidate) { remain[j]++; } } @@ -1737,12 +1735,12 @@ pmerge(PyObject *acc, PyObject* to_merge) } if (empty_cnt != to_merge_size) { - set_mro_error(to_merge, remain); + set_mro_error(to_merge, to_merge_size, remain); res = -1; } out: - PyMem_FREE(remain); + PyMem_Del(remain); return res; } @@ -1750,10 +1748,9 @@ pmerge(PyObject *acc, PyObject* to_merge) static PyObject * mro_implementation(PyTypeObject *type) { - PyObject *result = NULL; + PyObject *result; PyObject *bases; - PyObject *to_merge, *bases_aslist; - int res; + PyObject **to_merge; Py_ssize_t i, n; if (type->tp_dict == NULL) { @@ -1762,21 +1759,25 @@ mro_implementation(PyTypeObject *type) } bases = type->tp_bases; + assert(PyTuple_Check(bases)); n = PyTuple_GET_SIZE(bases); - if (n == 1) { - /* Fast path: if there is a single base, constructing the MRO - * is trivial. - */ - PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); - Py_ssize_t k; - + for (i = 0; i < n; i++) { + PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); if (base->tp_mro == NULL) { PyErr_Format(PyExc_TypeError, "Cannot extend an incomplete type '%.100s'", base->tp_name); return NULL; } - k = PyTuple_GET_SIZE(base->tp_mro); + assert(PyTuple_Check(base->tp_mro)); + } + + if (n == 1) { + /* Fast path: if there is a single base, constructing the MRO + * is trivial. + */ + PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); + Py_ssize_t k = PyTuple_GET_SIZE(base->tp_mro); result = PyTuple_New(k + 1); if (result == NULL) { return NULL; @@ -1791,59 +1792,45 @@ mro_implementation(PyTypeObject *type) return result; } + /* This is just a basic sanity check. */ + if (check_duplicates(bases) < 0) { + return NULL; + } + /* Find a superclass linearization that honors the constraints - of the explicit lists of bases and the constraints implied by + of the explicit tuples of bases and the constraints implied by each base class. - to_merge is a list of lists, where each list is a superclass + to_merge is an array of tuples, where each tuple is a superclass linearization implied by a base class. The last element of - to_merge is the declared list of bases. + to_merge is the declared tuple of bases. */ - to_merge = PyList_New(n+1); - if (to_merge == NULL) + to_merge = PyMem_New(PyObject *, n + 1); + if (to_merge == NULL) { + PyErr_NoMemory(); return NULL; + } for (i = 0; i < n; i++) { - PyTypeObject *base; - PyObject *base_mro_aslist; - - base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); - if (base->tp_mro == NULL) { - PyErr_Format(PyExc_TypeError, - "Cannot extend an incomplete type '%.100s'", - base->tp_name); - goto out; - } - - base_mro_aslist = PySequence_List(base->tp_mro); - if (base_mro_aslist == NULL) - goto out; - - PyList_SET_ITEM(to_merge, i, base_mro_aslist); + PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); + to_merge[i] = base->tp_mro; } + to_merge[n] = bases; - bases_aslist = PySequence_List(bases); - if (bases_aslist == NULL) - goto out; - /* This is just a basic sanity check. */ - if (check_duplicates(bases_aslist) < 0) { - Py_DECREF(bases_aslist); - goto out; + result = PyList_New(1); + if (result == NULL) { + PyMem_Del(to_merge); + return NULL; } - PyList_SET_ITEM(to_merge, n, bases_aslist); - - result = Py_BuildValue("[O]", (PyObject *)type); - if (result == NULL) - goto out; - res = pmerge(result, to_merge); - if (res < 0) + Py_INCREF(type); + PyList_SET_ITEM(result, 0, (PyObject *)type); + if (pmerge(result, to_merge, n + 1) < 0) { Py_CLEAR(result); + } - out: - Py_DECREF(to_merge); - + PyMem_Del(to_merge); return result; } From webhook-mailer at python.org Wed Dec 20 13:06:24 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Wed, 20 Dec 2017 18:06:24 -0000 Subject: [Python-checkins] bpo-32306: Clarify c.f.Executor.map() documentation (#4947) Message-ID: https://github.com/python/cpython/commit/a7a751dd7b08a5bb6cb399c1b2a6ca7b24aba51d commit: a7a751dd7b08a5bb6cb399c1b2a6ca7b24aba51d branch: master author: Antoine Pitrou committer: GitHub date: 2017-12-20T19:06:20+01:00 summary: bpo-32306: Clarify c.f.Executor.map() documentation (#4947) The built-in map() function collects function arguments lazily, but concurrent.futures.Executor.map() does so eagerly. files: M Doc/library/concurrent.futures.rst diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index d4b698e1c17..707d24dc252 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -40,21 +40,29 @@ Executor Objects .. method:: map(func, *iterables, timeout=None, chunksize=1) - Equivalent to :func:`map(func, *iterables) ` except *func* is executed - asynchronously and several calls to *func* may be made concurrently. The - returned iterator raises a :exc:`concurrent.futures.TimeoutError` if - :meth:`~iterator.__next__` is called and the result isn't available + Similar to :func:`map(func, *iterables) ` except: + + * the *iterables* are collected immediately rather than lazily; + + * *func* is executed asynchronously and several calls to + *func* may be made concurrently. + + The returned iterator raises a :exc:`concurrent.futures.TimeoutError` + if :meth:`~iterator.__next__` is called and the result isn't available after *timeout* seconds from the original call to :meth:`Executor.map`. *timeout* can be an int or a float. If *timeout* is not specified or - ``None``, there is no limit to the wait time. If a call raises an - exception, then that exception will be raised when its value is - retrieved from the iterator. When using :class:`ProcessPoolExecutor`, this - method chops *iterables* into a number of chunks which it submits to the - pool as separate tasks. The (approximate) size of these chunks can be - specified by setting *chunksize* to a positive integer. For very long - iterables, using a large value for *chunksize* can significantly improve - performance compared to the default size of 1. With :class:`ThreadPoolExecutor`, - *chunksize* has no effect. + ``None``, there is no limit to the wait time. + + If a *func* call raises an exception, then that exception will be + raised when its value is retrieved from the iterator. + + When using :class:`ProcessPoolExecutor`, this method chops *iterables* + into a number of chunks which it submits to the pool as separate + tasks. The (approximate) size of these chunks can be specified by + setting *chunksize* to a positive integer. For very long iterables, + using a large value for *chunksize* can significantly improve + performance compared to the default size of 1. With + :class:`ThreadPoolExecutor`, *chunksize* has no effect. .. versionchanged:: 3.5 Added the *chunksize* argument. From webhook-mailer at python.org Wed Dec 20 13:19:20 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Wed, 20 Dec 2017 18:19:20 -0000 Subject: [Python-checkins] bpo-32306: Clarify c.f.Executor.map() documentation (GH-4947) (#4948) Message-ID: https://github.com/python/cpython/commit/4aa84e728565a15a82727b9b971126e355f47e9d commit: 4aa84e728565a15a82727b9b971126e355f47e9d branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Antoine Pitrou date: 2017-12-20T19:19:18+01:00 summary: bpo-32306: Clarify c.f.Executor.map() documentation (GH-4947) (#4948) The built-in map() function collects function arguments lazily, but concurrent.futures.Executor.map() does so eagerly. (cherry picked from commit a7a751dd7b08a5bb6cb399c1b2a6ca7b24aba51d) files: M Doc/library/concurrent.futures.rst diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index d85576b8bed..9794e735d42 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -40,21 +40,29 @@ Executor Objects .. method:: map(func, *iterables, timeout=None, chunksize=1) - Equivalent to :func:`map(func, *iterables) ` except *func* is executed - asynchronously and several calls to *func* may be made concurrently. The - returned iterator raises a :exc:`concurrent.futures.TimeoutError` if - :meth:`~iterator.__next__` is called and the result isn't available + Similar to :func:`map(func, *iterables) ` except: + + * the *iterables* are collected immediately rather than lazily; + + * *func* is executed asynchronously and several calls to + *func* may be made concurrently. + + The returned iterator raises a :exc:`concurrent.futures.TimeoutError` + if :meth:`~iterator.__next__` is called and the result isn't available after *timeout* seconds from the original call to :meth:`Executor.map`. *timeout* can be an int or a float. If *timeout* is not specified or - ``None``, there is no limit to the wait time. If a call raises an - exception, then that exception will be raised when its value is - retrieved from the iterator. When using :class:`ProcessPoolExecutor`, this - method chops *iterables* into a number of chunks which it submits to the - pool as separate tasks. The (approximate) size of these chunks can be - specified by setting *chunksize* to a positive integer. For very long - iterables, using a large value for *chunksize* can significantly improve - performance compared to the default size of 1. With :class:`ThreadPoolExecutor`, - *chunksize* has no effect. + ``None``, there is no limit to the wait time. + + If a *func* call raises an exception, then that exception will be + raised when its value is retrieved from the iterator. + + When using :class:`ProcessPoolExecutor`, this method chops *iterables* + into a number of chunks which it submits to the pool as separate + tasks. The (approximate) size of these chunks can be specified by + setting *chunksize* to a positive integer. For very long iterables, + using a large value for *chunksize* can significantly improve + performance compared to the default size of 1. With + :class:`ThreadPoolExecutor`, *chunksize* has no effect. .. versionchanged:: 3.5 Added the *chunksize* argument. From webhook-mailer at python.org Wed Dec 20 13:24:46 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 20 Dec 2017 18:24:46 -0000 Subject: [Python-checkins] bpo-29970: Make ssh_handshake_timeout None by default (#4939) Message-ID: https://github.com/python/cpython/commit/51eb1c6b9c0b382dfd6e0428eacff0c7891a6fc3 commit: 51eb1c6b9c0b382dfd6e0428eacff0c7891a6fc3 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-20T20:24:43+02:00 summary: bpo-29970: Make ssh_handshake_timeout None by default (#4939) * Make ssh_handshake_timeout None by default. * Raise ValueError if ssl_handshake_timeout is used without ssl. * Raise ValueError if ssl_handshake_timeout is not positive. files: M Doc/library/asyncio-eventloop.rst M Lib/asyncio/base_events.py M Lib/asyncio/events.py M Lib/asyncio/proactor_events.py M Lib/asyncio/sslproto.py M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_sslproto.py M Lib/test/test_asyncio/test_unix_events.py diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index d20e995d353..5dd258df312 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -261,7 +261,7 @@ Tasks Creating connections -------------------- -.. coroutinemethod:: AbstractEventLoop.create_connection(protocol_factory, host=None, port=None, \*, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=10.0) +.. coroutinemethod:: AbstractEventLoop.create_connection(protocol_factory, host=None, port=None, \*, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None) Create a streaming transport connection to a given Internet *host* and *port*: socket family :py:data:`~socket.AF_INET` or @@ -327,6 +327,7 @@ Creating connections * *ssl_handshake_timeout* is (for an SSL connection) the time in seconds to wait for the SSL handshake to complete before aborting the connection. + ``10.0`` seconds if ``None`` (default). .. versionadded:: 3.7 @@ -393,7 +394,7 @@ Creating connections :ref:`UDP echo server protocol ` examples. -.. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path=None, \*, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=10.0) +.. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path=None, \*, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None) Create UNIX connection: socket family :py:data:`~socket.AF_UNIX`, socket type :py:data:`~socket.SOCK_STREAM`. The :py:data:`~socket.AF_UNIX` socket @@ -423,7 +424,7 @@ Creating connections Creating listening connections ------------------------------ -.. coroutinemethod:: AbstractEventLoop.create_server(protocol_factory, host=None, port=None, \*, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=10.0) +.. coroutinemethod:: AbstractEventLoop.create_server(protocol_factory, host=None, port=None, \*, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None) Create a TCP server (socket type :data:`~socket.SOCK_STREAM`) bound to *host* and *port*. @@ -469,6 +470,7 @@ Creating listening connections * *ssl_handshake_timeout* is (for an SSL server) the time in seconds to wait for the SSL handshake to complete before aborting the connection. + ``10.0`` seconds if ``None`` (default). .. versionadded:: 3.7 @@ -488,7 +490,7 @@ Creating listening connections The *host* parameter can now be a sequence of strings. -.. coroutinemethod:: AbstractEventLoop.create_unix_server(protocol_factory, path=None, \*, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=10.0) +.. coroutinemethod:: AbstractEventLoop.create_unix_server(protocol_factory, path=None, \*, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None) Similar to :meth:`AbstractEventLoop.create_server`, but specific to the socket family :py:data:`~socket.AF_UNIX`. @@ -507,7 +509,7 @@ Creating listening connections The *path* parameter can now be a :class:`~pathlib.Path` object. -.. coroutinemethod:: BaseEventLoop.connect_accepted_socket(protocol_factory, sock, \*, ssl=None, ssl_handshake_timeout=10.0) +.. coroutinemethod:: BaseEventLoop.connect_accepted_socket(protocol_factory, sock, \*, ssl=None, ssl_handshake_timeout=None) Handle an accepted connection. @@ -524,6 +526,7 @@ Creating listening connections * *ssl_handshake_timeout* is (for an SSL connection) the time in seconds to wait for the SSL handshake to complete before aborting the connection. + ``10.0`` seconds if ``None`` (default). When completed it returns a ``(transport, protocol)`` pair. diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 6246f4e221c..2ab8a76e0c5 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -29,7 +29,6 @@ import warnings import weakref -from . import constants from . import coroutines from . import events from . import futures @@ -280,7 +279,7 @@ def _make_ssl_transport( self, rawsock, protocol, sslcontext, waiter=None, *, server_side=False, server_hostname=None, extra=None, server=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): """Create SSL transport.""" raise NotImplementedError @@ -643,7 +642,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): """Connect to a TCP server. Create a streaming transport connection to a given Internet host and @@ -674,6 +673,10 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): 'when using ssl without a host') server_hostname = host + if ssl_handshake_timeout is not None and not ssl: + raise ValueError( + 'ssl_handshake_timeout is only meaningful with ssl') + if host is not None or port is not None: if sock is not None: raise ValueError( @@ -769,7 +772,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): async def _create_connection_transport( self, sock, protocol_factory, ssl, server_hostname, server_side=False, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): sock.setblocking(False) @@ -948,7 +951,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): ssl=None, reuse_address=None, reuse_port=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): """Create a TCP server. The host parameter can be a string, in that case the TCP server is @@ -966,6 +969,11 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): """ if isinstance(ssl, bool): raise TypeError('ssl argument must be an SSLContext or None') + + if ssl_handshake_timeout is not None and ssl is None: + raise ValueError( + 'ssl_handshake_timeout is only meaningful with ssl') + if host is not None or port is not None: if sock is not None: raise ValueError( @@ -1046,7 +1054,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): async def connect_accepted_socket( self, protocol_factory, sock, *, ssl=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): """Handle an accepted connection. This is used by servers that accept connections outside of @@ -1058,6 +1066,10 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): if sock.type != socket.SOCK_STREAM: raise ValueError(f'A Stream Socket was expected, got {sock!r}') + if ssl_handshake_timeout is not None and not ssl: + raise ValueError( + 'ssl_handshake_timeout is only meaningful with ssl') + transport, protocol = await self._create_connection_transport( sock, protocol_factory, ssl, '', server_side=True, ssl_handshake_timeout=ssl_handshake_timeout) diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index c9033c020f3..3a5dbadbb10 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -17,7 +17,6 @@ import sys import threading -from . import constants from . import format_helpers @@ -255,7 +254,7 @@ def set_default_executor(self, executor): *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): raise NotImplementedError async def create_server( @@ -263,7 +262,7 @@ def set_default_executor(self, executor): *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): """A coroutine which creates a TCP server bound to host and port. The return value is a Server object which can be used to stop @@ -310,13 +309,13 @@ def set_default_executor(self, executor): self, protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): raise NotImplementedError async def create_unix_server( self, protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): """A coroutine which creates a UNIX Domain Socket server. The return value is a Server object, which can be used to stop diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index bc319b06ed6..2661cddef73 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -393,7 +393,7 @@ def _make_ssl_transport( self, rawsock, protocol, sslcontext, waiter=None, *, server_side=False, server_hostname=None, extra=None, server=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): ssl_protocol = sslproto.SSLProtocol( self, protocol, sslcontext, waiter, server_side, server_hostname, @@ -491,7 +491,7 @@ def _write_to_self(self): def _start_serving(self, protocol_factory, sock, sslcontext=None, server=None, backlog=100, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): def loop(f=None): try: diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 8bcc6cc0433..2d377c4ae39 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -402,10 +402,17 @@ class SSLProtocol(protocols.Protocol): def __init__(self, loop, app_protocol, sslcontext, waiter, server_side=False, server_hostname=None, call_connection_made=True, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): if ssl is None: raise RuntimeError('stdlib ssl module not available') + if ssl_handshake_timeout is None: + ssl_handshake_timeout = constants.SSL_HANDSHAKE_TIMEOUT + elif ssl_handshake_timeout <= 0: + raise ValueError( + f"ssl_handshake_timeout should be a positive number, " + f"got {ssl_handshake_timeout}") + if not sslcontext: sslcontext = _create_transport_context( server_side, server_hostname) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index e2344582268..69c719c3239 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -196,7 +196,7 @@ def _child_watcher_callback(self, pid, returncode, transp): self, protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): assert server_hostname is None or isinstance(server_hostname, str) if ssl: if server_hostname is None: @@ -205,6 +205,9 @@ def _child_watcher_callback(self, pid, returncode, transp): else: if server_hostname is not None: raise ValueError('server_hostname is only meaningful with ssl') + if ssl_handshake_timeout is not None: + raise ValueError( + 'ssl_handshake_timeout is only meaningful with ssl') if path is not None: if sock is not None: @@ -237,10 +240,14 @@ def _child_watcher_callback(self, pid, returncode, transp): async def create_unix_server( self, protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, - ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT): + ssl_handshake_timeout=None): if isinstance(ssl, bool): raise TypeError('ssl argument must be an SSLContext or None') + if ssl_handshake_timeout is not None and not ssl: + raise ValueError( + 'ssl_handshake_timeout is only meaningful with ssl') + if path is not None: if sock is not None: raise ValueError( diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 488257b341f..1fc74737026 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1053,6 +1053,14 @@ def test_create_server_wrong_sock(self): 'A Stream Socket was expected'): self.loop.run_until_complete(coro) + def test_create_server_ssl_timeout_for_plain_socket(self): + coro = self.loop.create_server( + MyProto, 'example.com', 80, ssl_handshake_timeout=1) + with self.assertRaisesRegex( + ValueError, + 'ssl_handshake_timeout is only meaningful with ssl'): + self.loop.run_until_complete(coro) + @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), 'no socket.SOCK_NONBLOCK (linux only)') def test_create_server_stream_bittype(self): @@ -1362,6 +1370,14 @@ def test_create_connection_ssl_server_hostname_errors(self): self.addCleanup(sock.close) self.assertRaises(ValueError, self.loop.run_until_complete, coro) + def test_create_connection_ssl_timeout_for_plain_socket(self): + coro = self.loop.create_connection( + MyProto, 'example.com', 80, ssl_handshake_timeout=1) + with self.assertRaisesRegex( + ValueError, + 'ssl_handshake_timeout is only meaningful with ssl'): + self.loop.run_until_complete(coro) + def test_create_server_empty_host(self): # if host is empty string use None instead host = object() diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 58e94d46da8..aefa33ba251 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -852,6 +852,16 @@ def test_ssl_connect_accepted_socket(self): self.test_connect_accepted_socket(server_context, client_context) + def test_connect_accepted_socket_ssl_timeout_for_plain_socket(self): + sock = socket.socket() + self.addCleanup(sock.close) + coro = self.loop.connect_accepted_socket( + MyProto, sock, ssl_handshake_timeout=1) + with self.assertRaisesRegex( + ValueError, + 'ssl_handshake_timeout is only meaningful with ssl'): + self.loop.run_until_complete(coro) + @mock.patch('asyncio.base_events.socket') def create_server_multiple_hosts(self, family, hosts, mock_sock): @asyncio.coroutine diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 1c42a35128f..a7498e85c25 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -75,6 +75,22 @@ def test_handshake_timeout(self): self.loop.run_until_complete(tasks.sleep(0.2, loop=self.loop)) self.assertTrue(transport.abort.called) + def test_handshake_timeout_zero(self): + sslcontext = test_utils.dummy_ssl_context() + app_proto = mock.Mock() + waiter = mock.Mock() + with self.assertRaisesRegex(ValueError, 'a positive number'): + sslproto.SSLProtocol(self.loop, app_proto, sslcontext, waiter, + ssl_handshake_timeout=0) + + def test_handshake_timeout_negative(self): + sslcontext = test_utils.dummy_ssl_context() + app_proto = mock.Mock() + waiter = mock.Mock() + with self.assertRaisesRegex(ValueError, 'a positive number'): + sslproto.SSLProtocol(self.loop, app_proto, sslcontext, waiter, + ssl_handshake_timeout=-10) + def test_eof_received_waiter(self): waiter = asyncio.Future(loop=self.loop) ssl_proto = self.ssl_protocol(waiter) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index e13cc3749da..097d0ef73dc 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -327,6 +327,14 @@ def test_create_unix_server_path_stream_bittype(self): finally: os.unlink(fn) + def test_create_unix_server_ssl_timeout_with_plain_sock(self): + coro = self.loop.create_unix_server(lambda: None, path='spam', + ssl_handshake_timeout=1) + with self.assertRaisesRegex( + ValueError, + 'ssl_handshake_timeout is only meaningful with ssl'): + self.loop.run_until_complete(coro) + def test_create_unix_connection_path_inetsock(self): sock = socket.socket() with sock: @@ -383,6 +391,15 @@ def test_create_unix_connection_ssl_noserverhost(self): self.loop.run_until_complete(coro) + def test_create_unix_connection_ssl_timeout_with_plain_sock(self): + coro = self.loop.create_unix_connection(lambda: None, path='spam', + ssl_handshake_timeout=1) + with self.assertRaisesRegex( + ValueError, + 'ssl_handshake_timeout is only meaningful with ssl'): + self.loop.run_until_complete(coro) + + class UnixReadPipeTransportTests(test_utils.TestCase): From webhook-mailer at python.org Wed Dec 20 13:36:49 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 20 Dec 2017 18:36:49 -0000 Subject: [Python-checkins] bpo-32030: Complete _PyCoreConfig_Read() (#4946) Message-ID: https://github.com/python/cpython/commit/9cfc00262c7f6b93072762eed1dc5d94fa3897f0 commit: 9cfc00262c7f6b93072762eed1dc5d94fa3897f0 branch: master author: Victor Stinner committer: GitHub date: 2017-12-20T19:36:46+01:00 summary: bpo-32030: Complete _PyCoreConfig_Read() (#4946) * Add _PyCoreConfig.install_signal_handlers * Remove _PyMain.config: _PyMainInterpreterConfig usage is now restricted to pymain_init_python_main(). * Rename _PyMain.core_config to _PyMain.config * _PyMainInterpreterConfig_Read() now creates the xoptions dictionary from the core config * Fix _PyMainInterpreterConfig_Read(): don't replace xoptions and argv if they are already set. files: M Include/pystate.h M Modules/main.c M Python/pylifecycle.c diff --git a/Include/pystate.h b/Include/pystate.h index 619e627bf36..a4815286a74 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -25,6 +25,7 @@ typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int); typedef struct { + int install_signal_handlers; /* Install signal handlers? -1 means unset */ int ignore_environment; /* -E */ int use_hash_seed; /* PYTHONHASHSEED=x */ unsigned long hash_seed; @@ -62,6 +63,7 @@ typedef struct { #define _PyCoreConfig_INIT \ (_PyCoreConfig){ \ + .install_signal_handlers = -1, \ .use_hash_seed = -1, \ .coerce_c_locale = -1, \ .utf8_mode = -1, \ @@ -73,7 +75,7 @@ typedef struct { * See PEP 432 for final anticipated contents */ typedef struct { - int install_signal_handlers; + int install_signal_handlers; /* Install signal handlers? -1 means unset */ PyObject *argv; /* sys.argv list, can be NULL */ PyObject *executable; /* sys.executable str */ PyObject *prefix; /* sys.prefix str */ diff --git a/Modules/main.c b/Modules/main.c index 385a09e2747..0a36f9db9d8 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -164,7 +164,7 @@ pymain_usage(int error, const wchar_t* program) static const char* -pymain_get_env_var(const char *name) +config_get_env_var(const char *name) { const char *var = Py_GETENV(name); if (var && var[0] != '\0') { @@ -223,7 +223,7 @@ config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name) static void pymain_run_startup(PyCompilerFlags *cf) { - const char *startup = pymain_get_env_var("PYTHONSTARTUP"); + const char *startup = config_get_env_var("PYTHONSTARTUP"); if (startup == NULL) { return; } @@ -477,15 +477,13 @@ typedef struct { wchar_t *command; /* -c argument */ wchar_t *module; /* -m argument */ - _PyCoreConfig core_config; - _PyMainInterpreterConfig config; + _PyCoreConfig config; PyObject *main_importer_path; } _PyMain; #define _PyMain_INIT \ - {.core_config = _PyCoreConfig_INIT, \ - .config = _PyMainInterpreterConfig_INIT, \ + {.config = _PyCoreConfig_INIT, \ .err = _Py_INIT_OK()} /* Note: _PyMain_INIT sets other fields to 0/NULL */ @@ -559,8 +557,8 @@ pymain_init_cmdline_argv(_PyMain *pymain, _Py_CommandLineDetails *cmdline) else { program = L""; } - pymain->core_config.program = pymain_wstrdup(pymain, program); - if (pymain->core_config.program == NULL) { + pymain->config.program = pymain_wstrdup(pymain, program); + if (pymain->config.program == NULL) { return -1; } @@ -607,16 +605,14 @@ pymain_clear_pymain(_PyMain *pymain) } static void -pymain_clear_configs(_PyMain *pymain) +pymain_clear_config(_PyMain *pymain) { - _PyMainInterpreterConfig_Clear(&pymain->config); - /* Clear core config with the memory allocator used by pymain_read_conf() */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _PyCoreConfig_Clear(&pymain->core_config); + _PyCoreConfig_Clear(&pymain->config); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } @@ -626,7 +622,6 @@ static void pymain_free_python(_PyMain *pymain) { Py_CLEAR(pymain->main_importer_path); - _PyMainInterpreterConfig_Clear(&pymain->config); #ifdef __INSURE__ /* Insure++ is a memory analysis tool that aids in discovering @@ -658,7 +653,7 @@ pymain_free_raw(_PyMain *pymain) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _PyCoreConfig_Clear(&pymain->core_config); + _PyCoreConfig_Clear(&pymain->config); pymain_clear_pymain(pymain); clear_wstrlist(orig_argc, orig_argv); @@ -702,24 +697,35 @@ pymain_run_main_from_importer(_PyMain *pymain) } -static int -pymain_wstrlist_append(_PyMain *pymain, int *len, wchar_t ***list, const wchar_t *str) +static _PyInitError +wstrlist_append(int *len, wchar_t ***list, const wchar_t *str) { - wchar_t *str2 = pymain_wstrdup(pymain, str); + wchar_t *str2 = _PyMem_RawWcsdup(str); if (str2 == NULL) { - return -1; + return _Py_INIT_NO_MEMORY(); } size_t size = (*len + 1) * sizeof(list[0]); wchar_t **list2 = (wchar_t **)PyMem_RawRealloc(*list, size); if (list2 == NULL) { PyMem_RawFree(str2); - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; + return _Py_INIT_NO_MEMORY(); } list2[*len] = str2; *list = list2; (*len)++; + return _Py_INIT_OK(); +} + + +static int +pymain_wstrlist_append(_PyMain *pymain, int *len, wchar_t ***list, const wchar_t *str) +{ + _PyInitError err = wstrlist_append(len, list, str); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; + return -1; + } return 0; } @@ -731,6 +737,8 @@ pymain_wstrlist_append(_PyMain *pymain, int *len, wchar_t ***list, const wchar_t static int pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { + _PyCoreConfig *config = &pymain->config; + _PyOS_ResetGetOpt(); do { int longindex = -1; @@ -799,7 +807,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) break; case 'I': - pymain->core_config.ignore_environment++; + config->ignore_environment++; cmdline->isolated++; cmdline->no_user_site_directory++; break; @@ -823,7 +831,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) break; case 'E': - pymain->core_config.ignore_environment++; + config->ignore_environment++; break; case 't': @@ -862,8 +870,8 @@ pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) case 'X': if (pymain_wstrlist_append(pymain, - &pymain->core_config.nxoption, - &pymain->core_config.xoptions, + &config->nxoption, + &config->xoptions, _PyOS_optarg) < 0) { return -1; } @@ -874,7 +882,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) break; case 'R': - pymain->core_config.use_hash_seed = 0; + config->use_hash_seed = 0; break; /* This space reserved for other options */ @@ -903,7 +911,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) static int -pymain_add_xoption(PyObject *opts, const wchar_t *s) +add_xoption(PyObject *opts, const wchar_t *s) { PyObject *name, *value; @@ -933,48 +941,51 @@ pymain_add_xoption(PyObject *opts, const wchar_t *s) return -1; } -static int -pymain_init_xoptions_dict(_PyMain *pymain) + +static PyObject* +config_create_xoptions_dict(const _PyCoreConfig *config) { - int nxoption = pymain->core_config.nxoption; - wchar_t **xoptions = pymain->core_config.xoptions; + int nxoption = config->nxoption; + wchar_t **xoptions = config->xoptions; PyObject *dict = PyDict_New(); if (dict == NULL) { - return -1; + return NULL; } for (int i=0; i < nxoption; i++) { wchar_t *option = xoptions[i]; - if (pymain_add_xoption(dict, option) < 0) { + if (add_xoption(dict, option) < 0) { Py_DECREF(dict); - return -1; + return NULL; } } - pymain->config.xoptions = dict; - return 0; + return dict; } -static int -pymain_add_warnings_optlist(_PyMain *pymain, int len, wchar_t **options) +static _PyInitError +config_add_warnings_optlist(_PyCoreConfig *config, int len, wchar_t **options) { for (int i = 0; i < len; i++) { - if (pymain_wstrlist_append(pymain, - &pymain->core_config.nwarnoption, - &pymain->core_config.warnoptions, - options[i]) < 0) - { - return -1; + _PyInitError err = wstrlist_append(&config->nwarnoption, + &config->warnoptions, + options[i]); + if (_Py_INIT_FAILED(err)) { + return err; } } - return 0; + return _Py_INIT_OK(); } -static int -pymain_init_warnoptions(_PyMain *pymain, _Py_CommandLineDetails *cmdline) +static _PyInitError +config_init_warnoptions(_PyCoreConfig *config, _Py_CommandLineDetails *cmdline) { + _PyInitError err; + + assert(config->nwarnoption == 0); + /* The priority order for warnings configuration is (highest precedence * first): * @@ -990,22 +1001,27 @@ pymain_init_warnoptions(_PyMain *pymain, _Py_CommandLineDetails *cmdline) * the lowest precedence entries first so that later entries override them. */ - if (pymain->core_config.dev_mode) { - if (pymain_wstrlist_append(pymain, - &pymain->core_config.nwarnoption, - &pymain->core_config.warnoptions, - L"default") < 0) - { - return -1; + if (config->dev_mode) { + err = wstrlist_append(&config->nwarnoption, + &config->warnoptions, + L"default"); + if (_Py_INIT_FAILED(err)) { + return err; } } - if (pymain_add_warnings_optlist(pymain, cmdline->nenv_warnoption, cmdline->env_warnoptions) < 0) { - return -1; + err = config_add_warnings_optlist(config, + cmdline->nenv_warnoption, + cmdline->env_warnoptions); + if (_Py_INIT_FAILED(err)) { + return err; } - if (pymain_add_warnings_optlist(pymain, cmdline->nwarnoption, cmdline->warnoptions) < 0) { - return -1; + err = config_add_warnings_optlist(config, + cmdline->nwarnoption, + cmdline->warnoptions); + if (_Py_INIT_FAILED(err)) { + return err; } /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c @@ -1020,29 +1036,28 @@ pymain_init_warnoptions(_PyMain *pymain, _Py_CommandLineDetails *cmdline) else { filter = L"default::BytesWarning"; } - if (pymain_wstrlist_append(pymain, - &pymain->core_config.nwarnoption, - &pymain->core_config.warnoptions, - filter) < 0) - { - return -1; + err = wstrlist_append(&config->nwarnoption, + &config->warnoptions, + filter); + if (_Py_INIT_FAILED(err)) { + return err; } } - return 0; + return _Py_INIT_OK(); } static int -config_init_warnoptions(_PyMainInterpreterConfig *config, - const _PyCoreConfig *core_config) +main_config_init_warnoptions(_PyMainInterpreterConfig *main_config, + const _PyCoreConfig *config) { PyObject *warnoptions = PyList_New(0); if (warnoptions == NULL) { return -1; } - for (int i = 0; i < core_config->nwarnoption; i++) { - PyObject *option = PyUnicode_FromWideChar(core_config->warnoptions[i], -1); + for (int i = 0; i < config->nwarnoption; i++) { + PyObject *option = PyUnicode_FromWideChar(config->warnoptions[i], -1); if (option == NULL) { goto error; } @@ -1053,7 +1068,7 @@ config_init_warnoptions(_PyMainInterpreterConfig *config, Py_DECREF(option); } - config->warnoptions = warnoptions; + main_config->warnoptions = warnoptions; return 0; error: @@ -1065,22 +1080,21 @@ config_init_warnoptions(_PyMainInterpreterConfig *config, /* Get warning options from PYTHONWARNINGS environment variable. Return 0 on success. Set pymain->err and return -1 on error. */ -static int -pymain_warnings_envvar(_PyMain *pymain, _Py_CommandLineDetails *cmdline) +static _PyInitError +cmdline_init_env_warnoptions(_Py_CommandLineDetails *cmdline) { if (Py_IgnoreEnvironmentFlag) { - return 0; + return _Py_INIT_OK(); } wchar_t *env; int res = config_get_env_var_dup(&env, L"PYTHONWARNINGS", "PYTHONWARNINGS"); if (res < 0) { - pymain->err = DECODE_LOCALE_ERR("PYTHONWARNINGS", res); - return -1; + return DECODE_LOCALE_ERR("PYTHONWARNINGS", res); } if (env == NULL) { - return 0; + return _Py_INIT_OK(); } @@ -1089,17 +1103,16 @@ pymain_warnings_envvar(_PyMain *pymain, _Py_CommandLineDetails *cmdline) warning != NULL; warning = WCSTOK(NULL, L",", &context)) { - if (pymain_wstrlist_append(pymain, - &cmdline->nenv_warnoption, - &cmdline->env_warnoptions, - warning) < 0) - { + _PyInitError err = wstrlist_append(&cmdline->nenv_warnoption, + &cmdline->env_warnoptions, + warning); + if (_Py_INIT_FAILED(err)) { PyMem_RawFree(env); - return -1; + return err; } } PyMem_RawFree(env); - return 0; + return _Py_INIT_OK(); } @@ -1170,7 +1183,7 @@ config_init_program_name(_PyCoreConfig *config) so the actual executable path is passed in an environment variable. See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ - const char *p = pymain_get_env_var("PYTHONEXECUTABLE"); + const char *p = config_get_env_var("PYTHONEXECUTABLE"); if (p != NULL) { size_t len; wchar_t* program_name = Py_DecodeLocale(p, &len); @@ -1304,23 +1317,22 @@ pymain_init_core_argv(_PyMain *pymain, _Py_CommandLineDetails *cmdline) argv[0] = arg0; } - pymain->core_config.argc = argc; - pymain->core_config.argv = argv; + pymain->config.argc = argc; + pymain->config.argv = argv; return 0; } static int -config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_config) +main_config_init_argv(_PyMainInterpreterConfig *main_config, + const _PyCoreConfig *config) { - assert(config->argv == NULL); - - if (core_config->argc < 0) { + if (config->argc < 0) { return 0; } - int argc = core_config->argc; - wchar_t** argv = core_config->argv; + int argc = config->argc; + wchar_t** argv = config->argv; assert(argc >= 1 && argv != NULL); PyObject *list = PyList_New(argc); @@ -1337,13 +1349,13 @@ config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_con PyList_SET_ITEM(list, i, v); } - config->argv = list; + main_config->argv = list; return 0; } static int -pymain_init_path0(_PyMain *pymain, PyObject **path0) +pymain_compute_path0(_PyMain *pymain, PyObject **path0) { if (pymain->main_importer_path != NULL) { /* Let pymain_run_main_from_importer() adjust sys.path[0] later */ @@ -1356,8 +1368,8 @@ pymain_init_path0(_PyMain *pymain, PyObject **path0) return 0; } - *path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc, - pymain->core_config.argv); + *path0 = _PyPathConfig_ComputeArgv0(pymain->config.argc, + pymain->config.argv); if (*path0 == NULL) { pymain->err = _Py_INIT_NO_MEMORY(); return -1; @@ -1408,8 +1420,8 @@ pymain_get_global_config(_PyMain *pymain, _Py_CommandLineDetails *cmdline) #endif cmdline->check_hash_pycs_mode = _Py_CheckHashBasedPycsMode ; - pymain->core_config.ignore_environment = Py_IgnoreEnvironmentFlag; - pymain->core_config.utf8_mode = Py_UTF8Mode; + pymain->config.ignore_environment = Py_IgnoreEnvironmentFlag; + pymain->config.utf8_mode = Py_UTF8Mode; } @@ -1435,12 +1447,12 @@ pymain_set_global_config(_PyMain *pymain, _Py_CommandLineDetails *cmdline) Py_LegacyWindowsStdioFlag = cmdline->legacy_windows_stdio; #endif - Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; - Py_UTF8Mode = pymain->core_config.utf8_mode; + Py_IgnoreEnvironmentFlag = pymain->config.ignore_environment; + Py_UTF8Mode = pymain->config.utf8_mode; /* Random or non-zero hash seed */ - Py_HashRandomizationFlag = (pymain->core_config.use_hash_seed == 0 || - pymain->core_config.hash_seed != 0); + Py_HashRandomizationFlag = (pymain->config.use_hash_seed == 0 || + pymain->config.hash_seed != 0); } @@ -1483,7 +1495,7 @@ pymain_open_filename(_PyMain *pymain) else cfilename = ""; fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n", - pymain->core_config.program, cfilename, err, strerror(err)); + pymain->config.program, cfilename, err, strerror(err)); PyMem_Free(cfilename_buffer); pymain->status = 2; return NULL; @@ -1506,7 +1518,7 @@ pymain_open_filename(_PyMain *pymain) S_ISDIR(sb.st_mode)) { fprintf(stderr, "%ls: '%ls' is a directory, cannot continue\n", - pymain->core_config.program, pymain->filename); + pymain->config.program, pymain->filename); fclose(fp); pymain->status = 1; return NULL; @@ -1550,7 +1562,7 @@ pymain_repl(_PyMain *pymain, PyCompilerFlags *cf) { /* Check this environment variable at the end, to give programs the opportunity to set it from Python. */ - if (!Py_InspectFlag && pymain_get_env_var("PYTHONINSPECT")) { + if (!Py_InspectFlag && config_get_env_var("PYTHONINSPECT")) { Py_InspectFlag = 1; } @@ -1580,7 +1592,7 @@ pymain_parse_cmdline(_PyMain *pymain, _Py_CommandLineDetails *cmdline) return -1; } if (res) { - pymain_usage(1, pymain->core_config.program); + pymain_usage(1, pymain->config.program); pymain->status = 2; return 1; } @@ -1595,10 +1607,10 @@ pymain_parse_cmdline(_PyMain *pymain, _Py_CommandLineDetails *cmdline) static const wchar_t* -pymain_get_xoption(_PyMain *pymain, wchar_t *name) +config_get_xoption(_PyCoreConfig *config, wchar_t *name) { - int nxoption = pymain->core_config.nxoption; - wchar_t **xoptions = pymain->core_config.xoptions; + int nxoption = config->nxoption; + wchar_t **xoptions = config->xoptions; for (int i=0; i < nxoption; i++) { wchar_t *option = xoptions[i]; size_t len; @@ -1653,13 +1665,13 @@ pymain_wstr_to_int(const wchar_t *wstr, int *result) } -static int -pymain_init_tracemalloc(_PyMain *pymain) +static _PyInitError +pymain_init_tracemalloc(_PyCoreConfig *config) { int nframe; int valid; - const char *env = pymain_get_env_var("PYTHONTRACEMALLOC"); + const char *env = config_get_env_var("PYTHONTRACEMALLOC"); if (env) { if (!pymain_str_to_int(env, &nframe)) { valid = (nframe >= 1); @@ -1668,14 +1680,13 @@ pymain_init_tracemalloc(_PyMain *pymain) valid = 0; } if (!valid) { - pymain->err = _Py_INIT_USER_ERR("PYTHONTRACEMALLOC: invalid " - "number of frames"); - return -1; + return _Py_INIT_USER_ERR("PYTHONTRACEMALLOC: invalid number " + "of frames"); } - pymain->core_config.tracemalloc = nframe; + config->tracemalloc = nframe; } - const wchar_t *xoption = pymain_get_xoption(pymain, L"tracemalloc"); + const wchar_t *xoption = config_get_xoption(config, L"tracemalloc"); if (xoption) { const wchar_t *sep = wcschr(xoption, L'='); if (sep) { @@ -1686,25 +1697,24 @@ pymain_init_tracemalloc(_PyMain *pymain) valid = 0; } if (!valid) { - pymain->err = _Py_INIT_USER_ERR("-X tracemalloc=NFRAME: " - "invalid number of frames"); - return -1; + return _Py_INIT_USER_ERR("-X tracemalloc=NFRAME: " + "invalid number of frames"); } } else { /* -X tracemalloc behaves as -X tracemalloc=1 */ nframe = 1; } - pymain->core_config.tracemalloc = nframe; + config->tracemalloc = nframe; } - return 0; + return _Py_INIT_OK(); } static void -pymain_get_env_flag(int *flag, const char *name) +get_env_flag(int *flag, const char *name) { - const char *var = pymain_get_env_var(name); + const char *var = config_get_env_var(name); if (!var) { return; } @@ -1720,44 +1730,24 @@ pymain_get_env_flag(int *flag, const char *name) static void -pymain_get_env_flags(_PyMain *pymain, _Py_CommandLineDetails *cmdline) -{ - pymain_get_env_flag(&cmdline->debug, - "PYTHONDEBUG"); - pymain_get_env_flag(&cmdline->verbosity, - "PYTHONVERBOSE"); - pymain_get_env_flag(&cmdline->optimization_level, - "PYTHONOPTIMIZE"); - pymain_get_env_flag(&cmdline->inspect, - "PYTHONINSPECT"); - pymain_get_env_flag(&cmdline->dont_write_bytecode, - "PYTHONDONTWRITEBYTECODE"); - pymain_get_env_flag(&cmdline->no_user_site_directory, - "PYTHONNOUSERSITE"); - pymain_get_env_flag(&cmdline->use_unbuffered_io, - "PYTHONUNBUFFERED"); +cmdline_get_env_flags(_Py_CommandLineDetails *cmdline) +{ + get_env_flag(&cmdline->debug, "PYTHONDEBUG"); + get_env_flag(&cmdline->verbosity, "PYTHONVERBOSE"); + get_env_flag(&cmdline->optimization_level, "PYTHONOPTIMIZE"); + get_env_flag(&cmdline->inspect, "PYTHONINSPECT"); + get_env_flag(&cmdline->dont_write_bytecode, "PYTHONDONTWRITEBYTECODE"); + get_env_flag(&cmdline->no_user_site_directory, "PYTHONNOUSERSITE"); + get_env_flag(&cmdline->use_unbuffered_io, "PYTHONUNBUFFERED"); #ifdef MS_WINDOWS - pymain_get_env_flag(&cmdline->legacy_windows_fs_encoding, - "PYTHONLEGACYWINDOWSFSENCODING"); - pymain_get_env_flag(&cmdline->legacy_windows_stdio, - "PYTHONLEGACYWINDOWSSTDIO"); + get_env_flag(&cmdline->legacy_windows_fs_encoding, + "PYTHONLEGACYWINDOWSFSENCODING"); + get_env_flag(&cmdline->legacy_windows_stdio, + "PYTHONLEGACYWINDOWSSTDIO"); #endif } -static _PyInitError -config_init_module_search_path_env(_PyCoreConfig *config) -{ - wchar_t *path; - int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH"); - if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONHOME", res); - } - config->module_search_path_env = path; - return _Py_INIT_OK(); -} - - static _PyInitError config_init_home(_PyCoreConfig *config) { @@ -1786,7 +1776,7 @@ static _PyInitError config_init_hash_seed(_PyCoreConfig *config) { if (config->use_hash_seed < 0) { - const char *seed_text = pymain_get_env_var("PYTHONHASHSEED"); + const char *seed_text = config_get_env_var("PYTHONHASHSEED"); int use_hash_seed; unsigned long hash_seed; if (_Py_ReadHashSeed(seed_text, &use_hash_seed, &hash_seed) < 0) { @@ -1800,121 +1790,121 @@ config_init_hash_seed(_PyCoreConfig *config) } -static int -pymain_init_utf8_mode(_PyMain *pymain, _Py_CommandLineDetails *cmdline) +static _PyInitError +config_init_utf8_mode(_PyCoreConfig *config) { - _PyCoreConfig *core_config = &pymain->core_config; - -#ifdef MS_WINDOWS - if (cmdline->legacy_windows_fs_encoding) { - core_config->utf8_mode = 0; - return 0; + /* The option was already set by Py_UTF8Mode, + Py_LegacyWindowsFSEncodingFlag or PYTHONLEGACYWINDOWSFSENCODING. */ + if (config->utf8_mode >= 0) { + return _Py_INIT_OK(); } -#endif - const wchar_t *xopt = pymain_get_xoption(pymain, L"utf8"); + const wchar_t *xopt = config_get_xoption(config, L"utf8"); if (xopt) { wchar_t *sep = wcschr(xopt, L'='); if (sep) { xopt = sep + 1; if (wcscmp(xopt, L"1") == 0) { - core_config->utf8_mode = 1; + config->utf8_mode = 1; } else if (wcscmp(xopt, L"0") == 0) { - core_config->utf8_mode = 0; + config->utf8_mode = 0; } else { - pymain->err = _Py_INIT_USER_ERR("invalid -X utf8 option value"); - return -1; + return _Py_INIT_USER_ERR("invalid -X utf8 option value"); } } else { - core_config->utf8_mode = 1; + config->utf8_mode = 1; } - return 0; + return _Py_INIT_OK(); } - const char *opt = pymain_get_env_var("PYTHONUTF8"); + const char *opt = config_get_env_var("PYTHONUTF8"); if (opt) { if (strcmp(opt, "1") == 0) { - core_config->utf8_mode = 1; + config->utf8_mode = 1; } else if (strcmp(opt, "0") == 0) { - core_config->utf8_mode = 0; + config->utf8_mode = 0; } else { - pymain->err = _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment " - "variable value"); - return -1; + return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment " + "variable value"); } - return 0; + return _Py_INIT_OK(); } - return 0; + + return _Py_INIT_OK(); } -static int -pymain_parse_envvars(_PyMain *pymain, _Py_CommandLineDetails *cmdline) +static _PyInitError +config_read_env_vars(_PyCoreConfig *config) { - _PyCoreConfig *core_config = &pymain->core_config; - - /* Get environment variables */ - pymain_get_env_flags(pymain, cmdline); - - if (pymain_warnings_envvar(pymain, cmdline) < 0) { - return -1; - } - - core_config->allocator = pymain_get_env_var("PYTHONMALLOC"); - - /* -X options */ - if (pymain_get_xoption(pymain, L"showrefcount")) { - core_config->show_ref_count = 1; - } - if (pymain_get_xoption(pymain, L"showalloccount")) { - core_config->show_alloc_count = 1; - } + config->allocator = config_get_env_var("PYTHONMALLOC"); - /* More complex options: env var and/or -X option */ - if (pymain_get_env_var("PYTHONFAULTHANDLER") - || pymain_get_xoption(pymain, L"faulthandler")) { - core_config->faulthandler = 1; - } - if (pymain_get_env_var("PYTHONPROFILEIMPORTTIME") - || pymain_get_xoption(pymain, L"importtime")) { - core_config->import_time = 1; - } - if (pymain_init_tracemalloc(pymain) < 0) { - return -1; - } - if (pymain_get_xoption(pymain, L"dev" ) || - pymain_get_env_var("PYTHONDEVMODE")) - { - core_config->dev_mode = 1; - core_config->faulthandler = 1; - core_config->allocator = "debug"; - } - if (pymain_get_env_var("PYTHONDUMPREFS")) { - pymain->core_config.dump_refs = 1; + if (config_get_env_var("PYTHONDUMPREFS")) { + config->dump_refs = 1; } - if (pymain_get_env_var("PYTHONMALLOCSTATS")) { - pymain->core_config.malloc_stats = 1; + if (config_get_env_var("PYTHONMALLOCSTATS")) { + config->malloc_stats = 1; } - const char* env = pymain_get_env_var("PYTHONCOERCECLOCALE"); + const char *env = config_get_env_var("PYTHONCOERCECLOCALE"); if (env) { if (strcmp(env, "0") == 0) { - pymain->core_config.coerce_c_locale = 0; + config->coerce_c_locale = 0; } else if (strcmp(env, "warn") == 0) { - pymain->core_config.coerce_c_locale_warn = 1; + config->coerce_c_locale_warn = 1; } else { - pymain->core_config.coerce_c_locale = 1; + config->coerce_c_locale = 1; } } - return 0; + wchar_t *path; + int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH"); + if (res < 0) { + return DECODE_LOCALE_ERR("PYTHONHOME", res); + } + config->module_search_path_env = path; + + _PyInitError err = config_init_hash_seed(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + return _Py_INIT_OK(); +} + + +static _PyInitError +config_read_complex_options(_PyCoreConfig *config) +{ + /* More complex options configured by env var and -X option */ + if (config_get_env_var("PYTHONFAULTHANDLER") + || config_get_xoption(config, L"faulthandler")) { + config->faulthandler = 1; + } + if (config_get_env_var("PYTHONPROFILEIMPORTTIME") + || config_get_xoption(config, L"importtime")) { + config->import_time = 1; + } + if (config_get_xoption(config, L"dev" ) || + config_get_env_var("PYTHONDEVMODE")) + { + config->dev_mode = 1; + config->faulthandler = 1; + config->allocator = "debug"; + } + + _PyInitError err = pymain_init_tracemalloc(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + return _Py_INIT_OK(); } @@ -1927,27 +1917,37 @@ pymain_parse_envvars(_PyMain *pymain, _Py_CommandLineDetails *cmdline) static int pymain_read_conf_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { + _PyInitError err; + int res = pymain_parse_cmdline(pymain, cmdline); if (res != 0) { return res; } - if (pymain_init_core_argv(pymain, cmdline) < 0) { - return -1; - } - /* Set Py_IgnoreEnvironmentFlag for Py_GETENV() */ - Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; + _PyCoreConfig *config = &pymain->config; + Py_IgnoreEnvironmentFlag = config->ignore_environment; - if (pymain_parse_envvars(pymain, cmdline) < 0) { + /* Get environment variables */ + cmdline_get_env_flags(cmdline); + + err = cmdline_init_env_warnoptions(cmdline); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; return -1; } - if (pymain_init_utf8_mode(pymain, cmdline) < 0) { +#ifdef MS_WINDOWS + if (cmdline->legacy_windows_fs_encoding) { + config->utf8_mode = 0; + } +#endif + + if (pymain_init_core_argv(pymain, cmdline) < 0) { return -1; } - _PyInitError err = _PyCoreConfig_Read(&pymain->core_config); + err = _PyCoreConfig_Read(config); if (_Py_INIT_FAILED(err)) { pymain->err = err; return -1; @@ -1979,10 +1979,10 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) int locale_coerced = 0; int loops = 0; - int init_ignore_env = pymain->core_config.ignore_environment; + int init_ignore_env = pymain->config.ignore_environment; while (1) { - int utf8_mode = pymain->core_config.utf8_mode; + int utf8_mode = pymain->config.utf8_mode; int encoding_changed = 0; /* Watchdog to prevent an infinite loop */ @@ -1997,8 +1997,9 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) goto done; } - res = pymain_read_conf_impl(pymain, cmdline); - if (res != 0) { + int conf_res = pymain_read_conf_impl(pymain, cmdline); + if (conf_res != 0) { + res = conf_res; goto done; } @@ -2012,20 +2013,20 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) * See the documentation of the PYTHONCOERCECLOCALE setting for more * details. */ - if (pymain->core_config.coerce_c_locale == 1 && !locale_coerced) { + if (pymain->config.coerce_c_locale == 1 && !locale_coerced) { locale_coerced = 1; - _Py_CoerceLegacyLocale(&pymain->core_config); + _Py_CoerceLegacyLocale(&pymain->config); encoding_changed = 1; } if (utf8_mode == -1) { - if (pymain->core_config.utf8_mode == 1) { + if (pymain->config.utf8_mode == 1) { /* UTF-8 Mode enabled */ encoding_changed = 1; } } else { - if (pymain->core_config.utf8_mode != utf8_mode) { + if (pymain->config.utf8_mode != utf8_mode) { encoding_changed = 1; } } @@ -2037,9 +2038,9 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) /* Reset the configuration, except UTF-8 Mode. Set Py_UTF8Mode for Py_DecodeLocale(). Reset Py_IgnoreEnvironmentFlag, modified by pymain_read_conf_impl(). */ - Py_UTF8Mode = pymain->core_config.utf8_mode; + Py_UTF8Mode = pymain->config.utf8_mode; Py_IgnoreEnvironmentFlag = init_ignore_env; - _PyCoreConfig_Clear(&pymain->core_config); + _PyCoreConfig_Clear(&pymain->config); pymain_clear_cmdline(pymain, cmdline); pymain_get_global_config(pymain, cmdline); @@ -2059,6 +2060,34 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) } +static void +config_init_locale(_PyCoreConfig *config) +{ + if (config->utf8_mode >= 0 && config->coerce_c_locale >= 0) { + return; + } + + if (_Py_LegacyLocaleDetected()) { + /* POSIX locale: enable C locale coercion and UTF-8 Mode */ + if (config->utf8_mode < 0) { + config->utf8_mode = 1; + } + if (config->coerce_c_locale < 0) { + config->coerce_c_locale = 1; + } + return; + } + + /* By default, C locale coercion and UTF-8 Mode are disabled */ + if (config->coerce_c_locale < 0) { + config->coerce_c_locale = 0; + } + if (config->utf8_mode < 0) { + config->utf8_mode = 0; + } +} + + /* Read configuration settings from standard locations * * This function doesn't make any changes to the interpreter state - it @@ -2074,42 +2103,46 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) _PyInitError _PyCoreConfig_Read(_PyCoreConfig *config) { - _PyInitError err = config_init_home(config); + _PyInitError err; + + err = config_read_env_vars(config); if (_Py_INIT_FAILED(err)) { return err; } - err = config_init_module_search_path_env(config); + /* -X options */ + if (config_get_xoption(config, L"showrefcount")) { + config->show_ref_count = 1; + } + if (config_get_xoption(config, L"showalloccount")) { + config->show_alloc_count = 1; + } + + err = config_read_complex_options(config); if (_Py_INIT_FAILED(err)) { return err; } - err = config_init_program_name(config); + err = config_init_utf8_mode(config); if (_Py_INIT_FAILED(err)) { return err; } - err = config_init_hash_seed(config); + err = config_init_home(config); if (_Py_INIT_FAILED(err)) { return err; } - if (config->utf8_mode < 0 || config->coerce_c_locale < 0) { - if (_Py_LegacyLocaleDetected()) { - if (config->utf8_mode < 0) { - config->utf8_mode = 1; - } - if (config->coerce_c_locale < 0) { - config->coerce_c_locale = 1; - } - } + err = config_init_program_name(config); + if (_Py_INIT_FAILED(err)) { + return err; + } - if (config->coerce_c_locale < 0) { - config->coerce_c_locale = 0; - } - if (config->utf8_mode < 0) { - config->utf8_mode = 0; - } + config_init_locale(config); + + /* Signal handlers are installed by default */ + if (config->install_signal_handlers < 0) { + config->install_signal_handlers = 1; } return _Py_INIT_OK(); @@ -2286,7 +2319,7 @@ _PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config, static PyObject * -config_create_path_list(const wchar_t *path, wchar_t delim) +create_path_list(const wchar_t *path, wchar_t delim) { int i, n; const wchar_t *p; @@ -2323,105 +2356,104 @@ config_create_path_list(const wchar_t *path, wchar_t delim) _PyInitError -_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_config) +_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config, + const _PyCoreConfig *config) { - _PyInitError err = _PyPathConfig_Init(core_config); + _PyInitError err = _PyPathConfig_Init(config); if (_Py_INIT_FAILED(err)) { return err; } - if (config_init_argv(config, core_config) < 0) { - return _Py_INIT_ERR("failed to create sys.argv"); + if (main_config->install_signal_handlers < 0) { + main_config->install_signal_handlers = config->install_signal_handlers; } - if (config_init_warnoptions(config, core_config) < 0) { - return _Py_INIT_NO_MEMORY(); + if (main_config->xoptions == NULL) { + main_config->xoptions = config_create_xoptions_dict(config); + if (main_config->xoptions == NULL) { + return _Py_INIT_NO_MEMORY(); + } } - /* Signal handlers are installed by default */ - if (config->install_signal_handlers < 0) { - config->install_signal_handlers = 1; + if (main_config->argv == NULL) { + if (main_config_init_argv(main_config, config) < 0) { + return _Py_INIT_ERR("failed to create sys.argv"); + } } - if (config->module_search_path == NULL && - !core_config->_disable_importlib) + if (main_config->warnoptions == NULL) { + if (main_config_init_warnoptions(main_config, config) < 0) { + return _Py_INIT_NO_MEMORY(); + } + } + if (main_config->module_search_path == NULL && + !config->_disable_importlib) { wchar_t *sys_path = Py_GetPath(); - config->module_search_path = config_create_path_list(sys_path, DELIM); - if (config->module_search_path == NULL) { + main_config->module_search_path = create_path_list(sys_path, DELIM); + if (main_config->module_search_path == NULL) { return _Py_INIT_NO_MEMORY(); } } - if (config->executable == NULL) { - config->executable = PyUnicode_FromWideChar(Py_GetProgramFullPath(), -1); - if (config->executable == NULL) { + if (main_config->executable == NULL) { + main_config->executable = PyUnicode_FromWideChar(Py_GetProgramFullPath(), -1); + if (main_config->executable == NULL) { return _Py_INIT_NO_MEMORY(); } } - if (config->prefix == NULL) { - config->prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1); - if (config->prefix == NULL) { + if (main_config->prefix == NULL) { + main_config->prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1); + if (main_config->prefix == NULL) { return _Py_INIT_NO_MEMORY(); } } - if (config->exec_prefix == NULL) { - config->exec_prefix = PyUnicode_FromWideChar(Py_GetExecPrefix(), -1); - if (config->exec_prefix == NULL) { + if (main_config->exec_prefix == NULL) { + main_config->exec_prefix = PyUnicode_FromWideChar(Py_GetExecPrefix(), -1); + if (main_config->exec_prefix == NULL) { return _Py_INIT_NO_MEMORY(); } } - if (config->base_prefix == NULL) { - Py_INCREF(config->prefix); - config->base_prefix = config->prefix; + if (main_config->base_prefix == NULL) { + Py_INCREF(main_config->prefix); + main_config->base_prefix = main_config->prefix; } - if (config->base_exec_prefix == NULL) { - Py_INCREF(config->exec_prefix); - config->base_exec_prefix = config->exec_prefix; + if (main_config->base_exec_prefix == NULL) { + Py_INCREF(main_config->exec_prefix); + main_config->base_exec_prefix = main_config->exec_prefix; } return _Py_INIT_OK(); } -static int -pymain_init_python_core(_PyMain *pymain) -{ - pymain_init_stdio(pymain); - - pymain->err = _Py_InitializeCore(&pymain->core_config); - if (_Py_INIT_FAILED(pymain->err)) { - return -1; - } - return 0; -} - - static int pymain_init_python_main(_PyMain *pymain) { - if (pymain_init_xoptions_dict(pymain)) { - pymain->err = _Py_INIT_NO_MEMORY(); - return -1; - } + _PyInitError err; - _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config, - &pymain->core_config); - if (_Py_INIT_FAILED(err)) { - pymain->err = err; - return -1; + _PyMainInterpreterConfig main_config = _PyMainInterpreterConfig_INIT; + err = _PyMainInterpreterConfig_Read(&main_config, &pymain->config); + if (!_Py_INIT_FAILED(err)) { + err = _Py_InitializeMainInterpreter(&main_config); } + _PyMainInterpreterConfig_Clear(&main_config); - err = _Py_InitializeMainInterpreter(&pymain->config); if (_Py_INIT_FAILED(err)) { pymain->err = err; return -1; } + return 0; +} + +static int +pymain_init_sys_path(_PyMain *pymain) +{ if (pymain->filename != NULL) { /* If filename is a package (ex: directory or ZIP file) which contains __main__.py, main_importer_path is set to filename and will be @@ -2431,11 +2463,11 @@ pymain_init_python_main(_PyMain *pymain) } PyObject *path0; - if (pymain_init_path0(pymain, &path0) < 0) { + if (pymain_compute_path0(pymain, &path0) < 0) { return -1; } - pymain_clear_configs(pymain); + pymain_clear_config(pymain); if (path0 != NULL) { if (pymain_update_sys_path(pymain, path0) < 0) { @@ -2444,7 +2476,6 @@ pymain_init_python_main(_PyMain *pymain) } Py_DECREF(path0); } - return 0; } @@ -2466,6 +2497,7 @@ pymain_run_python(_PyMain *pymain) else { pymain_run_filename(pymain, &cf); } + pymain_repl(pymain, &cf); } @@ -2482,7 +2514,7 @@ pymain_init(_PyMain *pymain) fedisableexcept(FE_OVERFLOW); #endif - pymain->core_config._disable_importlib = 0; + pymain->config._disable_importlib = 0; pymain->config.install_signal_handlers = 1; } @@ -2505,7 +2537,7 @@ pymain_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) } if (cmdline->print_help) { - pymain_usage(0, pymain->core_config.program); + pymain_usage(0, pymain->config.program); return 1; } @@ -2523,7 +2555,9 @@ pymain_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) } orig_argc = pymain->argc; - if (pymain_init_warnoptions(pymain, cmdline) < 0) { + _PyInitError err = config_init_warnoptions(&pymain->config, cmdline); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; return -1; } return 0; @@ -2571,7 +2605,10 @@ pymain_main(_PyMain *pymain) goto done; } - if (pymain_init_python_core(pymain) < 0) { + pymain_init_stdio(pymain); + + pymain->err = _Py_InitializeCore(&pymain->config); + if (_Py_INIT_FAILED(pymain->err)) { _Py_FatalInitError(pymain->err); } @@ -2579,6 +2616,10 @@ pymain_main(_PyMain *pymain) _Py_FatalInitError(pymain->err); } + if (pymain_init_sys_path(pymain) < 0) { + _Py_FatalInitError(pymain->err); + } + pymain_run_python(pymain); if (Py_FinalizeEx() < 0) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 79fcb5777e3..2af76d76d2b 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -874,30 +874,29 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) _PyInitError _Py_InitializeEx_Private(int install_sigs, int install_importlib) { - _PyCoreConfig core_config = _PyCoreConfig_INIT; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + _PyCoreConfig config = _PyCoreConfig_INIT; _PyInitError err; - core_config.ignore_environment = Py_IgnoreEnvironmentFlag; - core_config._disable_importlib = !install_importlib; + config.ignore_environment = Py_IgnoreEnvironmentFlag; + config._disable_importlib = !install_importlib; config.install_signal_handlers = install_sigs; - err = _PyCoreConfig_Read(&core_config); + err = _PyCoreConfig_Read(&config); if (_Py_INIT_FAILED(err)) { goto done; } - err = _Py_InitializeCore(&core_config); + err = _Py_InitializeCore(&config); if (_Py_INIT_FAILED(err)) { goto done; } - err = _PyMainInterpreterConfig_Read(&config, &core_config); - if (_Py_INIT_FAILED(err)) { - goto done; + _PyMainInterpreterConfig main_config = _PyMainInterpreterConfig_INIT; + err = _PyMainInterpreterConfig_Read(&main_config, &config); + if (!_Py_INIT_FAILED(err)) { + err = _Py_InitializeMainInterpreter(&main_config); } - - err = _Py_InitializeMainInterpreter(&config); + _PyMainInterpreterConfig_Clear(&main_config); if (_Py_INIT_FAILED(err)) { goto done; } @@ -905,8 +904,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) err = _Py_INIT_OK(); done: - _PyCoreConfig_Clear(&core_config); - _PyMainInterpreterConfig_Clear(&config); + _PyCoreConfig_Clear(&config); return err; } From webhook-mailer at python.org Wed Dec 20 16:36:15 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 20 Dec 2017 21:36:15 -0000 Subject: [Python-checkins] correct the typos (#4950) Message-ID: https://github.com/python/cpython/commit/83cb778b4a3f856f2243b0f0d36fefb5c44b388f commit: 83cb778b4a3f856f2243b0f0d36fefb5c44b388f branch: master author: Srinivas Reddy Thatiparthy (?????????? ?????? ?????????) committer: Andrew Svetlov date: 2017-12-20T23:36:10+02:00 summary: correct the typos (#4950) files: M Modules/_cursesmodule.c diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 42f4a85e356..7936aef0cc9 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1363,7 +1363,7 @@ PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; default: - PyErr_SetString(PyExc_TypeError, "insch requires 1 or 4 arguments"); + PyErr_SetString(PyExc_TypeError, "insch requires 1 to 4 arguments"); return NULL; } @@ -1394,7 +1394,7 @@ PyCursesWindow_InCh(PyCursesWindowObject *self, PyObject *args) rtn = mvwinch(self->win,y,x); break; default: - PyErr_SetString(PyExc_TypeError, "inch requires 0 or 2 arguments"); + PyErr_SetString(PyExc_TypeError, "inch requires 0 to 2 arguments"); return NULL; } return PyLong_FromUnsignedLong(rtn); From webhook-mailer at python.org Wed Dec 20 17:41:41 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 20 Dec 2017 22:41:41 -0000 Subject: [Python-checkins] bpo-32030: Fix usage of memory allocators (#4953) Message-ID: https://github.com/python/cpython/commit/31e99080f6f8cf7faaba9fe3a4e0996e49163317 commit: 31e99080f6f8cf7faaba9fe3a4e0996e49163317 branch: master author: Victor Stinner committer: GitHub date: 2017-12-20T23:41:38+01:00 summary: bpo-32030: Fix usage of memory allocators (#4953) * _Py_InitializeCore() doesn't call _PyMem_SetupAllocators() anymore if the PYTHONMALLOC environment variable is not set. * pymain_cmdline() now sets the allocator to the default, instead of setting the allocator in subfunctions. * Py_SetStandardStreamEncoding() now calls _PyMem_SetDefaultAllocator() to get a known allocator, to be able to release the memory with the same allocator. files: A Misc/NEWS.d/next/C API/2017-12-20-23-22-32.bpo-32030.d1dcwh.rst M Modules/main.c M Python/pylifecycle.c diff --git a/Misc/NEWS.d/next/C API/2017-12-20-23-22-32.bpo-32030.d1dcwh.rst b/Misc/NEWS.d/next/C API/2017-12-20-23-22-32.bpo-32030.d1dcwh.rst new file mode 100644 index 00000000000..8e8b430e247 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2017-12-20-23-22-32.bpo-32030.d1dcwh.rst @@ -0,0 +1,2 @@ +Py_Initialize() doesn't reset the memory allocators to default if the +``PYTHONMALLOC`` environment variable is not set. diff --git a/Modules/main.c b/Modules/main.c index 0a36f9db9d8..1bf706b162c 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -649,11 +649,12 @@ pymain_free_raw(_PyMain *pymain) Py_Initialize()-Py_Finalize() can be called multiple times. */ _PyPathConfig_Clear(&_Py_path_config); + pymain_clear_config(pymain); + /* Force the allocator used by pymain_read_conf() */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _PyCoreConfig_Clear(&pymain->config); pymain_clear_pymain(pymain); clear_wstrlist(orig_argc, orig_argv); @@ -1963,11 +1964,6 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) { int res = -1; - /* Force default allocator, since pymain_free() must use the same allocator - than this function. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - char *oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); if (oldloc == NULL) { pymain->err = _Py_INIT_NO_MEMORY(); @@ -2055,7 +2051,6 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline) PyMem_RawFree(oldloc); } - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return res; } @@ -2578,6 +2573,15 @@ pymain_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) static int pymain_cmdline(_PyMain *pymain) { + /* Force default allocator, since pymain_free() and pymain_clear_config() + must use the same allocator than this function. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +#ifdef Py_DEBUG + PyMemAllocatorEx default_alloc; + PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &default_alloc); +#endif + _Py_CommandLineDetails cmdline; memset(&cmdline, 0, sizeof(cmdline)); @@ -2588,6 +2592,14 @@ pymain_cmdline(_PyMain *pymain) pymain_set_global_config(pymain, &cmdline); pymain_clear_cmdline(pymain, &cmdline); + +#ifdef Py_DEBUG + /* Make sure that PYMEM_DOMAIN_RAW has not been modified */ + PyMemAllocatorEx cur_alloc; + PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &cur_alloc); + assert(memcmp(&cur_alloc, &default_alloc, sizeof(cur_alloc)) == 0); +#endif + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return res; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2af76d76d2b..560d0e36d49 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -172,6 +172,15 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) /* This is too late to have any effect */ return -1; } + + int res = 0; + + /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(), + but Py_Initialize() can change the allocator. Use a known allocator + to be able to release the memory later. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* Can't call PyErr_NoMemory() on errors, as Python hasn't been * initialised yet. * @@ -182,7 +191,8 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) if (encoding) { _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); if (!_Py_StandardStreamEncoding) { - return -2; + res = -2; + goto done; } } if (errors) { @@ -191,7 +201,8 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) if (_Py_StandardStreamEncoding) { PyMem_RawFree(_Py_StandardStreamEncoding); } - return -3; + res = -3; + goto done; } } #ifdef MS_WINDOWS @@ -200,7 +211,11 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) Py_LegacyWindowsStdioFlag = 1; } #endif - return 0; + +done: + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + return res; } @@ -597,8 +612,10 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) return err; } - if (_PyMem_SetupAllocators(core_config->allocator) < 0) { - return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator"); + if (core_config->allocator != NULL) { + if (_PyMem_SetupAllocators(core_config->allocator) < 0) { + return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator"); + } } if (_PyRuntime.initialized) { @@ -1818,7 +1835,11 @@ init_sys_streams(PyInterpreterState *interp) error: res = _Py_INIT_ERR("can't initialize sys standard streams"); + /* Use the same allocator than Py_SetStandardStreamEncoding() */ + PyMemAllocatorEx old_alloc; done: + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* We won't need them anymore. */ if (_Py_StandardStreamEncoding) { PyMem_RawFree(_Py_StandardStreamEncoding); @@ -1828,6 +1849,9 @@ init_sys_streams(PyInterpreterState *interp) PyMem_RawFree(_Py_StandardStreamErrors); _Py_StandardStreamErrors = NULL; } + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + PyMem_Free(pythonioencoding); Py_XDECREF(bimod); Py_XDECREF(iomod); From webhook-mailer at python.org Wed Dec 20 19:59:56 2017 From: webhook-mailer at python.org (INADA Naoki) Date: Thu, 21 Dec 2017 00:59:56 -0000 Subject: [Python-checkins] bpo-15216: io: TextIOWrapper.reconfigure() accepts encoding, errors and newline (GH-2343) Message-ID: https://github.com/python/cpython/commit/507434fd504f3ebc1da72aa77544edc0d73f136e commit: 507434fd504f3ebc1da72aa77544edc0d73f136e branch: master author: INADA Naoki committer: GitHub date: 2017-12-21T09:59:53+09:00 summary: bpo-15216: io: TextIOWrapper.reconfigure() accepts encoding, errors and newline (GH-2343) files: A Misc/NEWS.d/next/Library/2017-09-16-02-56-33.bpo-15216.lqXCTT.rst M Doc/library/io.rst M Lib/_pyio.py M Lib/test/test_io.py M Modules/_io/clinic/textio.c.h M Modules/_io/textio.c diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 6778058342d..5c71d900fd2 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -904,7 +904,7 @@ Text I/O locale encoding using :func:`locale.setlocale`, use the current locale encoding instead of the user preferred encoding. - :class:`TextIOWrapper` provides one attribute in addition to those of + :class:`TextIOWrapper` provides these members in addition to those of :class:`TextIOBase` and its parents: .. attribute:: line_buffering @@ -918,11 +918,19 @@ Text I/O .. versionadded:: 3.7 - .. method:: reconfigure(*, line_buffering=None, write_through=None) + .. method:: reconfigure(*[, encoding][, errors][, newline][, \ + line_buffering][, write_through]) - Reconfigure this text stream using new settings for *line_buffering* - and *write_through*. Passing ``None`` as an argument will retain - the current setting for that parameter. + Reconfigure this text stream using new settings for *encoding*, + *errors*, *newline*, *line_buffering* and *write_through*. + + Parameters not specified keep current settings, except + ``errors='strict`` is used when *encoding* is specified but + *errors* is not specified. + + It is not possible to change the encoding or newline if some data + has already been read from the stream. On the other hand, changing + encoding after write is possible. This method does an implicit stream flush before setting the new parameters. diff --git a/Lib/_pyio.py b/Lib/_pyio.py index b59a6509787..c91a647a2f6 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -1938,10 +1938,7 @@ class TextIOWrapper(TextIOBase): # so that the signature can match the signature of the C version. def __init__(self, buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False): - if newline is not None and not isinstance(newline, str): - raise TypeError("illegal newline type: %r" % (type(newline),)) - if newline not in (None, "", "\n", "\r", "\r\n"): - raise ValueError("illegal newline value: %r" % (newline,)) + self._check_newline(newline) if encoding is None: try: encoding = os.device_encoding(buffer.fileno()) @@ -1971,22 +1968,38 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None, raise ValueError("invalid errors: %r" % errors) self._buffer = buffer + self._decoded_chars = '' # buffer for text returned from decoder + self._decoded_chars_used = 0 # offset into _decoded_chars for read() + self._snapshot = None # info for reconstructing decoder state + self._seekable = self._telling = self.buffer.seekable() + self._has_read1 = hasattr(self.buffer, 'read1') + self._configure(encoding, errors, newline, + line_buffering, write_through) + + def _check_newline(self, newline): + if newline is not None and not isinstance(newline, str): + raise TypeError("illegal newline type: %r" % (type(newline),)) + if newline not in (None, "", "\n", "\r", "\r\n"): + raise ValueError("illegal newline value: %r" % (newline,)) + + def _configure(self, encoding=None, errors=None, newline=None, + line_buffering=False, write_through=False): self._encoding = encoding self._errors = errors + self._encoder = None + self._decoder = None + self._b2cratio = 0.0 + self._readuniversal = not newline self._readtranslate = newline is None self._readnl = newline self._writetranslate = newline != '' self._writenl = newline or os.linesep - self._encoder = None - self._decoder = None - self._decoded_chars = '' # buffer for text returned from decoder - self._decoded_chars_used = 0 # offset into _decoded_chars for read() - self._snapshot = None # info for reconstructing decoder state - self._seekable = self._telling = self.buffer.seekable() - self._has_read1 = hasattr(self.buffer, 'read1') - self._b2cratio = 0.0 + self._line_buffering = line_buffering + self._write_through = write_through + + # don't write a BOM in the middle of a file if self._seekable and self.writable(): position = self.buffer.tell() if position != 0: @@ -1996,12 +2009,6 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None, # Sometimes the encoder doesn't exist pass - self._configure(line_buffering, write_through) - - def _configure(self, line_buffering=False, write_through=False): - self._line_buffering = line_buffering - self._write_through = write_through - # self._snapshot is either None, or a tuple (dec_flags, next_input) # where dec_flags is the second (integer) item of the decoder state # and next_input is the chunk of input bytes that comes next after the @@ -2048,17 +2055,46 @@ def write_through(self): def buffer(self): return self._buffer - def reconfigure(self, *, line_buffering=None, write_through=None): + def reconfigure(self, *, + encoding=None, errors=None, newline=Ellipsis, + line_buffering=None, write_through=None): """Reconfigure the text stream with new parameters. This also flushes the stream. """ + if (self._decoder is not None + and (encoding is not None or errors is not None + or newline is not Ellipsis)): + raise UnsupportedOperation( + "It is not possible to set the encoding or newline of stream " + "after the first read") + + if errors is None: + if encoding is None: + errors = self._errors + else: + errors = 'strict' + elif not isinstance(errors, str): + raise TypeError("invalid errors: %r" % errors) + + if encoding is None: + encoding = self._encoding + else: + if not isinstance(encoding, str): + raise TypeError("invalid encoding: %r" % encoding) + + if newline is Ellipsis: + newline = self._readnl + self._check_newline(newline) + if line_buffering is None: line_buffering = self.line_buffering if write_through is None: write_through = self.write_through + self.flush() - self._configure(line_buffering, write_through) + self._configure(encoding, errors, newline, + line_buffering, write_through) def seekable(self): if self.closed: diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 9bfe4b0bc6e..3aee5f1083c 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -3408,6 +3408,123 @@ def seekable(self): return True F.tell = lambda x: 0 t = self.TextIOWrapper(F(), encoding='utf-8') + def test_reconfigure_encoding_read(self): + # latin1 -> utf8 + # (latin1 can decode utf-8 encoded string) + data = 'abc\xe9\n'.encode('latin1') + 'd\xe9f\n'.encode('utf8') + raw = self.BytesIO(data) + txt = self.TextIOWrapper(raw, encoding='latin1', newline='\n') + self.assertEqual(txt.readline(), 'abc\xe9\n') + with self.assertRaises(self.UnsupportedOperation): + txt.reconfigure(encoding='utf-8') + with self.assertRaises(self.UnsupportedOperation): + txt.reconfigure(newline=None) + + def test_reconfigure_write_fromascii(self): + # ascii has a specific encodefunc in the C implementation, + # but utf-8-sig has not. Make sure that we get rid of the + # cached encodefunc when we switch encoders. + raw = self.BytesIO() + txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n') + txt.write('foo\n') + txt.reconfigure(encoding='utf-8-sig') + txt.write('\xe9\n') + txt.flush() + self.assertEqual(raw.getvalue(), b'foo\n\xc3\xa9\n') + + def test_reconfigure_write(self): + # latin -> utf8 + raw = self.BytesIO() + txt = self.TextIOWrapper(raw, encoding='latin1', newline='\n') + txt.write('abc\xe9\n') + txt.reconfigure(encoding='utf-8') + self.assertEqual(raw.getvalue(), b'abc\xe9\n') + txt.write('d\xe9f\n') + txt.flush() + self.assertEqual(raw.getvalue(), b'abc\xe9\nd\xc3\xa9f\n') + + # ascii -> utf-8-sig: ensure that no BOM is written in the middle of + # the file + raw = self.BytesIO() + txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n') + txt.write('abc\n') + txt.reconfigure(encoding='utf-8-sig') + txt.write('d\xe9f\n') + txt.flush() + self.assertEqual(raw.getvalue(), b'abc\nd\xc3\xa9f\n') + + def test_reconfigure_write_non_seekable(self): + raw = self.BytesIO() + raw.seekable = lambda: False + raw.seek = None + txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n') + txt.write('abc\n') + txt.reconfigure(encoding='utf-8-sig') + txt.write('d\xe9f\n') + txt.flush() + + # If the raw stream is not seekable, there'll be a BOM + self.assertEqual(raw.getvalue(), b'abc\n\xef\xbb\xbfd\xc3\xa9f\n') + + def test_reconfigure_defaults(self): + txt = self.TextIOWrapper(self.BytesIO(), 'ascii', 'replace', '\n') + txt.reconfigure(encoding=None) + self.assertEqual(txt.encoding, 'ascii') + self.assertEqual(txt.errors, 'replace') + txt.write('LF\n') + + txt.reconfigure(newline='\r\n') + self.assertEqual(txt.encoding, 'ascii') + self.assertEqual(txt.errors, 'replace') + + txt.reconfigure(errors='ignore') + self.assertEqual(txt.encoding, 'ascii') + self.assertEqual(txt.errors, 'ignore') + txt.write('CRLF\n') + + txt.reconfigure(encoding='utf-8', newline=None) + self.assertEqual(txt.errors, 'strict') + txt.seek(0) + self.assertEqual(txt.read(), 'LF\nCRLF\n') + + self.assertEqual(txt.detach().getvalue(), b'LF\nCRLF\r\n') + + def test_reconfigure_newline(self): + raw = self.BytesIO(b'CR\rEOF') + txt = self.TextIOWrapper(raw, 'ascii', newline='\n') + txt.reconfigure(newline=None) + self.assertEqual(txt.readline(), 'CR\n') + raw = self.BytesIO(b'CR\rEOF') + txt = self.TextIOWrapper(raw, 'ascii', newline='\n') + txt.reconfigure(newline='') + self.assertEqual(txt.readline(), 'CR\r') + raw = self.BytesIO(b'CR\rLF\nEOF') + txt = self.TextIOWrapper(raw, 'ascii', newline='\r') + txt.reconfigure(newline='\n') + self.assertEqual(txt.readline(), 'CR\rLF\n') + raw = self.BytesIO(b'LF\nCR\rEOF') + txt = self.TextIOWrapper(raw, 'ascii', newline='\n') + txt.reconfigure(newline='\r') + self.assertEqual(txt.readline(), 'LF\nCR\r') + raw = self.BytesIO(b'CR\rCRLF\r\nEOF') + txt = self.TextIOWrapper(raw, 'ascii', newline='\r') + txt.reconfigure(newline='\r\n') + self.assertEqual(txt.readline(), 'CR\rCRLF\r\n') + + txt = self.TextIOWrapper(self.BytesIO(), 'ascii', newline='\r') + txt.reconfigure(newline=None) + txt.write('linesep\n') + txt.reconfigure(newline='') + txt.write('LF\n') + txt.reconfigure(newline='\n') + txt.write('LF\n') + txt.reconfigure(newline='\r') + txt.write('CR\n') + txt.reconfigure(newline='\r\n') + txt.write('CRLF\n') + expected = 'linesep' + os.linesep + 'LF\nLF\nCR\rCRLF\r\n' + self.assertEqual(txt.detach().getvalue().decode('ascii'), expected) + class MemviewBytesIO(io.BytesIO): '''A BytesIO object whose read method returns memoryviews diff --git a/Misc/NEWS.d/next/Library/2017-09-16-02-56-33.bpo-15216.lqXCTT.rst b/Misc/NEWS.d/next/Library/2017-09-16-02-56-33.bpo-15216.lqXCTT.rst new file mode 100644 index 00000000000..0e9fd558ff0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-16-02-56-33.bpo-15216.lqXCTT.rst @@ -0,0 +1,2 @@ +``TextIOWrapper.reconfigure()`` supports changing *encoding*, *errors*, and +*newline*. diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index 53ac0de89ab..60f5dab75c7 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -149,7 +149,7 @@ PyDoc_STRVAR(_io_TextIOWrapper___init____doc__, static int _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, - const char *encoding, const char *errors, + const char *encoding, PyObject *errors, const char *newline, int line_buffering, int write_through); @@ -158,10 +158,10 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; static const char * const _keywords[] = {"buffer", "encoding", "errors", "newline", "line_buffering", "write_through", NULL}; - static _PyArg_Parser _parser = {"O|zzzii:TextIOWrapper", _keywords, 0}; + static _PyArg_Parser _parser = {"O|zOzii:TextIOWrapper", _keywords, 0}; PyObject *buffer; const char *encoding = NULL; - const char *errors = NULL; + PyObject *errors = Py_None; const char *newline = NULL; int line_buffering = 0; int write_through = 0; @@ -177,7 +177,8 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) } PyDoc_STRVAR(_io_TextIOWrapper_reconfigure__doc__, -"reconfigure($self, /, *, line_buffering=None, write_through=None)\n" +"reconfigure($self, /, *, encoding=None, errors=None, newline=None,\n" +" line_buffering=None, write_through=None)\n" "--\n" "\n" "Reconfigure the text stream with new parameters.\n" @@ -188,7 +189,8 @@ PyDoc_STRVAR(_io_TextIOWrapper_reconfigure__doc__, {"reconfigure", (PyCFunction)_io_TextIOWrapper_reconfigure, METH_FASTCALL|METH_KEYWORDS, _io_TextIOWrapper_reconfigure__doc__}, static PyObject * -_io_TextIOWrapper_reconfigure_impl(textio *self, +_io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, + PyObject *errors, PyObject *newline_obj, PyObject *line_buffering_obj, PyObject *write_through_obj); @@ -196,16 +198,19 @@ static PyObject * _io_TextIOWrapper_reconfigure(textio *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"line_buffering", "write_through", NULL}; - static _PyArg_Parser _parser = {"|$OO:reconfigure", _keywords, 0}; + static const char * const _keywords[] = {"encoding", "errors", "newline", "line_buffering", "write_through", NULL}; + static _PyArg_Parser _parser = {"|$OOOOO:reconfigure", _keywords, 0}; + PyObject *encoding = Py_None; + PyObject *errors = Py_None; + PyObject *newline_obj = NULL; PyObject *line_buffering_obj = Py_None; PyObject *write_through_obj = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &line_buffering_obj, &write_through_obj)) { + &encoding, &errors, &newline_obj, &line_buffering_obj, &write_through_obj)) { goto exit; } - return_value = _io_TextIOWrapper_reconfigure_impl(self, line_buffering_obj, write_through_obj); + return_value = _io_TextIOWrapper_reconfigure_impl(self, encoding, errors, newline_obj, line_buffering_obj, write_through_obj); exit: return return_value; @@ -499,4 +504,4 @@ _io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { return _io_TextIOWrapper_close_impl(self); } -/*[clinic end generated code: output=679b3ac5284df4e0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b5be870b0039d577 input=a9049054013a1b77]*/ diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 5239e8518e6..6800d2dd253 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -36,6 +36,7 @@ _Py_IDENTIFIER(reset); _Py_IDENTIFIER(seek); _Py_IDENTIFIER(seekable); _Py_IDENTIFIER(setstate); +_Py_IDENTIFIER(strict); _Py_IDENTIFIER(tell); _Py_IDENTIFIER(writable); @@ -252,14 +253,14 @@ _io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self, Py_INCREF(decoder); if (errors == NULL) { - self->errors = PyUnicode_FromString("strict"); + self->errors = _PyUnicode_FromId(&PyId_strict); if (self->errors == NULL) return -1; } else { - Py_INCREF(errors); self->errors = errors; } + Py_INCREF(self->errors); self->translate = translate; self->seennl = 0; @@ -647,7 +648,7 @@ typedef struct PyObject *decoder; PyObject *readnl; PyObject *errors; - const char *writenl; /* utf-8 encoded, NULL stands for \n */ + const char *writenl; /* ASCII-encoded; NULL stands for \n */ char line_buffering; char write_through; char readuniversal; @@ -700,21 +701,21 @@ typedef struct static PyObject * ascii_encode(textio *self, PyObject *text) { - return _PyUnicode_AsASCIIString(text, PyBytes_AS_STRING(self->errors)); + return _PyUnicode_AsASCIIString(text, PyUnicode_AsUTF8(self->errors)); } static PyObject * utf16be_encode(textio *self, PyObject *text) { return _PyUnicode_EncodeUTF16(text, - PyBytes_AS_STRING(self->errors), 1); + PyUnicode_AsUTF8(self->errors), 1); } static PyObject * utf16le_encode(textio *self, PyObject *text) { return _PyUnicode_EncodeUTF16(text, - PyBytes_AS_STRING(self->errors), -1); + PyUnicode_AsUTF8(self->errors), -1); } static PyObject * @@ -729,21 +730,21 @@ utf16_encode(textio *self, PyObject *text) #endif } return _PyUnicode_EncodeUTF16(text, - PyBytes_AS_STRING(self->errors), 0); + PyUnicode_AsUTF8(self->errors), 0); } static PyObject * utf32be_encode(textio *self, PyObject *text) { return _PyUnicode_EncodeUTF32(text, - PyBytes_AS_STRING(self->errors), 1); + PyUnicode_AsUTF8(self->errors), 1); } static PyObject * utf32le_encode(textio *self, PyObject *text) { return _PyUnicode_EncodeUTF32(text, - PyBytes_AS_STRING(self->errors), -1); + PyUnicode_AsUTF8(self->errors), -1); } static PyObject * @@ -758,19 +759,19 @@ utf32_encode(textio *self, PyObject *text) #endif } return _PyUnicode_EncodeUTF32(text, - PyBytes_AS_STRING(self->errors), 0); + PyUnicode_AsUTF8(self->errors), 0); } static PyObject * utf8_encode(textio *self, PyObject *text) { - return _PyUnicode_AsUTF8String(text, PyBytes_AS_STRING(self->errors)); + return _PyUnicode_AsUTF8String(text, PyUnicode_AsUTF8(self->errors)); } static PyObject * latin1_encode(textio *self, PyObject *text) { - return _PyUnicode_AsLatin1String(text, PyBytes_AS_STRING(self->errors)); + return _PyUnicode_AsLatin1String(text, PyUnicode_AsUTF8(self->errors)); } /* Map normalized encoding names onto the specialized encoding funcs */ @@ -793,12 +794,198 @@ static const encodefuncentry encodefuncs[] = { {NULL, NULL} }; +static int +validate_newline(const char *newline) +{ + if (newline && newline[0] != '\0' + && !(newline[0] == '\n' && newline[1] == '\0') + && !(newline[0] == '\r' && newline[1] == '\0') + && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) { + PyErr_Format(PyExc_ValueError, + "illegal newline value: %s", newline); + return -1; + } + return 0; +} + +static int +set_newline(textio *self, const char *newline) +{ + PyObject *old = self->readnl; + if (newline == NULL) { + self->readnl = NULL; + } + else { + self->readnl = PyUnicode_FromString(newline); + if (self->readnl == NULL) { + self->readnl = old; + return -1; + } + } + self->readuniversal = (newline == NULL || newline[0] == '\0'); + self->readtranslate = (newline == NULL); + self->writetranslate = (newline == NULL || newline[0] != '\0'); + if (!self->readuniversal && self->readnl != NULL) { + // validate_newline() accepts only ASCII newlines. + assert(PyUnicode_KIND(self->readnl) == PyUnicode_1BYTE_KIND); + self->writenl = (const char *)PyUnicode_1BYTE_DATA(self->readnl); + if (strcmp(self->writenl, "\n") == 0) { + self->writenl = NULL; + } + } + else { +#ifdef MS_WINDOWS + self->writenl = "\r\n"; +#else + self->writenl = NULL; +#endif + } + Py_XDECREF(old); + return 0; +} + +static int +_textiowrapper_set_decoder(textio *self, PyObject *codec_info, + const char *errors) +{ + PyObject *res; + int r; + + res = _PyObject_CallMethodId(self->buffer, &PyId_readable, NULL); + if (res == NULL) + return -1; + + r = PyObject_IsTrue(res); + Py_DECREF(res); + if (r == -1) + return -1; + + if (r != 1) + return 0; + + Py_CLEAR(self->decoder); + self->decoder = _PyCodecInfo_GetIncrementalDecoder(codec_info, errors); + if (self->decoder == NULL) + return -1; + + if (self->readuniversal) { + PyObject *incrementalDecoder = PyObject_CallFunction( + (PyObject *)&PyIncrementalNewlineDecoder_Type, + "Oi", self->decoder, (int)self->readtranslate); + if (incrementalDecoder == NULL) + return -1; + Py_CLEAR(self->decoder); + self->decoder = incrementalDecoder; + } + + return 0; +} + +static PyObject* +_textiowrapper_decode(PyObject *decoder, PyObject *bytes, int eof) +{ + PyObject *chars; + + if (Py_TYPE(decoder) == &PyIncrementalNewlineDecoder_Type) + chars = _PyIncrementalNewlineDecoder_decode(decoder, bytes, eof); + else + chars = PyObject_CallMethodObjArgs(decoder, _PyIO_str_decode, bytes, + eof ? Py_True : Py_False, NULL); + + if (check_decoded(chars) < 0) + // check_decoded already decreases refcount + return NULL; + + return chars; +} + +static int +_textiowrapper_set_encoder(textio *self, PyObject *codec_info, + const char *errors) +{ + PyObject *res; + int r; + + res = _PyObject_CallMethodId(self->buffer, &PyId_writable, NULL); + if (res == NULL) + return -1; + + r = PyObject_IsTrue(res); + Py_DECREF(res); + if (r == -1) + return -1; + + if (r != 1) + return 0; + + Py_CLEAR(self->encoder); + self->encodefunc = NULL; + self->encoder = _PyCodecInfo_GetIncrementalEncoder(codec_info, errors); + if (self->encoder == NULL) + return -1; + + /* Get the normalized named of the codec */ + res = _PyObject_GetAttrId(codec_info, &PyId_name); + if (res == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + return -1; + } + else if (PyUnicode_Check(res)) { + const encodefuncentry *e = encodefuncs; + while (e->name != NULL) { + if (_PyUnicode_EqualToASCIIString(res, e->name)) { + self->encodefunc = e->encodefunc; + break; + } + e++; + } + } + Py_XDECREF(res); + + return 0; +} + +static int +_textiowrapper_fix_encoder_state(textio *self) +{ + if (!self->seekable || !self->encoder) { + return 0; + } + + self->encoding_start_of_stream = 1; + + PyObject *cookieObj = PyObject_CallMethodObjArgs( + self->buffer, _PyIO_str_tell, NULL); + if (cookieObj == NULL) { + return -1; + } + + int cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_EQ); + Py_DECREF(cookieObj); + if (cmp < 0) { + return -1; + } + + if (cmp == 0) { + self->encoding_start_of_stream = 0; + PyObject *res = PyObject_CallMethodObjArgs( + self->encoder, _PyIO_str_setstate, _PyLong_Zero, NULL); + if (res == NULL) { + return -1; + } + Py_DECREF(res); + } + + return 0; +} /*[clinic input] _io.TextIOWrapper.__init__ buffer: object encoding: str(accept={str, NoneType}) = NULL - errors: str(accept={str, NoneType}) = NULL + errors: object = None newline: str(accept={str, NoneType}) = NULL line_buffering: bool(accept={int}) = False write_through: bool(accept={int}) = False @@ -835,10 +1022,10 @@ write contains a newline character. static int _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, - const char *encoding, const char *errors, + const char *encoding, PyObject *errors, const char *newline, int line_buffering, int write_through) -/*[clinic end generated code: output=56a83402ce2a8381 input=598d10cc5f2ed7dd]*/ +/*[clinic end generated code: output=72267c0c01032ed2 input=1c5dd5d78bfcc675]*/ { PyObject *raw, *codec_info = NULL; _PyIO_State *state = NULL; @@ -848,12 +1035,20 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, self->ok = 0; self->detached = 0; - if (newline && newline[0] != '\0' - && !(newline[0] == '\n' && newline[1] == '\0') - && !(newline[0] == '\r' && newline[1] == '\0') - && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) { - PyErr_Format(PyExc_ValueError, - "illegal newline value: %s", newline); + if (errors == Py_None) { + errors = _PyUnicode_FromId(&PyId_strict); /* borrowed */ + } + else if (!PyUnicode_Check(errors)) { + // Check 'errors' argument here because Argument Clinic doesn't support + // 'str(accept={str, NoneType})' converter. + PyErr_Format( + PyExc_TypeError, + "TextIOWrapper() argument 'errors' must be str or None, not %.50s", + errors->ob_type->tp_name); + return -1; + } + + if (validate_newline(newline) < 0) { return -1; } @@ -955,99 +1150,29 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, * of the partially constructed object (like self->encoding) */ - if (errors == NULL) - errors = "strict"; - self->errors = PyBytes_FromString(errors); - if (self->errors == NULL) - goto error; - + Py_INCREF(errors); + self->errors = errors; self->chunk_size = 8192; - self->readuniversal = (newline == NULL || newline[0] == '\0'); self->line_buffering = line_buffering; self->write_through = write_through; - self->readtranslate = (newline == NULL); - if (newline) { - self->readnl = PyUnicode_FromString(newline); - if (self->readnl == NULL) - goto error; - } - self->writetranslate = (newline == NULL || newline[0] != '\0'); - if (!self->readuniversal && self->readnl) { - self->writenl = PyUnicode_AsUTF8(self->readnl); - if (self->writenl == NULL) - goto error; - if (!strcmp(self->writenl, "\n")) - self->writenl = NULL; + if (set_newline(self, newline) < 0) { + goto error; } -#ifdef MS_WINDOWS - else - self->writenl = "\r\n"; -#endif + + self->buffer = buffer; + Py_INCREF(buffer); /* Build the decoder object */ - res = _PyObject_CallMethodId(buffer, &PyId_readable, NULL); - if (res == NULL) + if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0) goto error; - r = PyObject_IsTrue(res); - Py_DECREF(res); - if (r == -1) - goto error; - if (r == 1) { - self->decoder = _PyCodecInfo_GetIncrementalDecoder(codec_info, - errors); - if (self->decoder == NULL) - goto error; - - if (self->readuniversal) { - PyObject *incrementalDecoder = PyObject_CallFunction( - (PyObject *)&PyIncrementalNewlineDecoder_Type, - "Oi", self->decoder, (int)self->readtranslate); - if (incrementalDecoder == NULL) - goto error; - Py_XSETREF(self->decoder, incrementalDecoder); - } - } /* Build the encoder object */ - res = _PyObject_CallMethodId(buffer, &PyId_writable, NULL); - if (res == NULL) - goto error; - r = PyObject_IsTrue(res); - Py_DECREF(res); - if (r == -1) + if (_textiowrapper_set_encoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0) goto error; - if (r == 1) { - self->encoder = _PyCodecInfo_GetIncrementalEncoder(codec_info, - errors); - if (self->encoder == NULL) - goto error; - /* Get the normalized name of the codec */ - res = _PyObject_GetAttrId(codec_info, &PyId_name); - if (res == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) - PyErr_Clear(); - else - goto error; - } - else if (PyUnicode_Check(res)) { - const encodefuncentry *e = encodefuncs; - while (e->name != NULL) { - if (_PyUnicode_EqualToASCIIString(res, e->name)) { - self->encodefunc = e->encodefunc; - break; - } - e++; - } - } - Py_XDECREF(res); - } /* Finished sorting out the codec details */ Py_CLEAR(codec_info); - self->buffer = buffer; - Py_INCREF(buffer); - if (Py_TYPE(buffer) == &PyBufferedReader_Type || Py_TYPE(buffer) == &PyBufferedWriter_Type || Py_TYPE(buffer) == &PyBufferedRandom_Type) { @@ -1077,30 +1202,8 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, self->has_read1 = _PyObject_HasAttrId(buffer, &PyId_read1); self->encoding_start_of_stream = 0; - if (self->seekable && self->encoder) { - PyObject *cookieObj; - int cmp; - - self->encoding_start_of_stream = 1; - - cookieObj = PyObject_CallMethodObjArgs(buffer, _PyIO_str_tell, NULL); - if (cookieObj == NULL) - goto error; - - cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_EQ); - Py_DECREF(cookieObj); - if (cmp < 0) { - goto error; - } - - if (cmp == 0) { - self->encoding_start_of_stream = 0; - res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate, - _PyLong_Zero, NULL); - if (res == NULL) - goto error; - Py_DECREF(res); - } + if (_textiowrapper_fix_encoder_state(self) < 0) { + goto error; } self->ok = 1; @@ -1129,10 +1232,57 @@ convert_optional_bool(PyObject *obj, int default_value) return v != 0; } +static int +textiowrapper_change_encoding(textio *self, PyObject *encoding, + PyObject *errors, int newline_changed) +{ + /* Use existing settings where new settings are not specified */ + if (encoding == Py_None && errors == Py_None && !newline_changed) { + return 0; // no change + } + + if (encoding == Py_None) { + encoding = self->encoding; + if (errors == Py_None) { + errors = self->errors; + } + } + else if (errors == Py_None) { + errors = _PyUnicode_FromId(&PyId_strict); + } + + const char *c_errors = PyUnicode_AsUTF8(errors); + if (c_errors == NULL) { + return -1; + } + + // Create new encoder & decoder + PyObject *codec_info = _PyCodec_LookupTextEncoding( + PyUnicode_AsUTF8(encoding), "codecs.open()"); + if (codec_info == NULL) { + return -1; + } + if (_textiowrapper_set_decoder(self, codec_info, c_errors) != 0 || + _textiowrapper_set_encoder(self, codec_info, c_errors) != 0) { + Py_DECREF(codec_info); + return -1; + } + Py_DECREF(codec_info); + + Py_INCREF(encoding); + Py_INCREF(errors); + Py_SETREF(self->encoding, encoding); + Py_SETREF(self->errors, errors); + + return _textiowrapper_fix_encoder_state(self); +} /*[clinic input] _io.TextIOWrapper.reconfigure * + encoding: object = None + errors: object = None + newline as newline_obj: object(c_default="NULL") = None line_buffering as line_buffering_obj: object = None write_through as write_through_obj: object = None @@ -1143,14 +1293,31 @@ This also does an implicit stream flush. [clinic start generated code]*/ static PyObject * -_io_TextIOWrapper_reconfigure_impl(textio *self, +_io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, + PyObject *errors, PyObject *newline_obj, PyObject *line_buffering_obj, PyObject *write_through_obj) -/*[clinic end generated code: output=7cdf79e7001e2856 input=baade27ecb9db7bc]*/ +/*[clinic end generated code: output=52b812ff4b3d4b0f input=671e82136e0f5822]*/ { int line_buffering; int write_through; - PyObject *res; + const char *newline = NULL; + + /* Check if something is in the read buffer */ + if (self->decoded_chars != NULL) { + if (encoding != Py_None || errors != Py_None || newline_obj != NULL) { + _unsupported("It is not possible to set the encoding or newline" + "of stream after the first read"); + return NULL; + } + } + + if (newline_obj != NULL && newline_obj != Py_None) { + newline = PyUnicode_AsUTF8(newline_obj); + if (newline == NULL || validate_newline(newline) < 0) { + return NULL; + } + } line_buffering = convert_optional_bool(line_buffering_obj, self->line_buffering); @@ -1159,11 +1326,23 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, if (line_buffering < 0 || write_through < 0) { return NULL; } - res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL); - Py_XDECREF(res); + + PyObject *res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); if (res == NULL) { return NULL; } + Py_DECREF(res); + self->b2cratio = 0; + + if (newline_obj != NULL && set_newline(self, newline) < 0) { + return NULL; + } + + if (textiowrapper_change_encoding( + self, encoding, errors, newline_obj != NULL) < 0) { + return NULL; + } + self->line_buffering = line_buffering; self->write_through = write_through; Py_RETURN_NONE; @@ -1565,18 +1744,12 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) nbytes = input_chunk_buf.len; eof = (nbytes == 0); - if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) { - decoded_chars = _PyIncrementalNewlineDecoder_decode( - self->decoder, input_chunk, eof); - } - else { - decoded_chars = PyObject_CallMethodObjArgs(self->decoder, - _PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL); - } - PyBuffer_Release(&input_chunk_buf); - if (check_decoded(decoded_chars) < 0) + decoded_chars = _textiowrapper_decode(self->decoder, input_chunk, eof); + PyBuffer_Release(&input_chunk_buf); + if (decoded_chars == NULL) goto fail; + textiowrapper_set_decoded_chars(self, decoded_chars); nchars = PyUnicode_GET_LENGTH(decoded_chars); if (nchars > 0) @@ -2851,7 +3024,8 @@ static PyObject * textiowrapper_errors_get(textio *self, void *context) { CHECK_INITIALIZED(self); - return PyUnicode_FromString(PyBytes_AS_STRING(self->errors)); + Py_INCREF(self->errors); + return self->errors; } static PyObject * From lp_benchmark_robot at intel.com Wed Dec 20 22:21:42 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 20 Dec 2017 19:21:42 -0800 Subject: [Python-checkins] [4 down, 61 flat] Results for Python (master branch) 2017-12-20 Message-ID: Results for project python/master, build date: 2017-12-20 03:03:37-08:00. - commit: 776407f - previous commit: 5d86246 - revision date: 2017-12-20 11:17:58+01:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.900% | -0.227% | +5.062% | +7.384% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.448% | -2.040% | +24.366% | +10.030% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 0.964% | -0.616% | +25.509% | +10.026% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.337% | +0.008% | +23.346% | +9.371% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 1.813% | -0.813% | +8.294% | +12.933% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.351% | +2.221% | +10.561% | +12.256% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.988% | +0.033% | +6.085% | +10.878% | +-----+------------------------+--------+------------+------------+------------+ | :-( | crypto_pyaes| 0.529% | -2.432% | -3.221% | +10.796% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 2.170% | -0.644% | +10.011% | +18.339% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.946% | +1.544% | +12.643% | +13.650% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.111% | -0.575% | +3.567% | +7.817% | +-----+------------------------+--------+------------+------------+------------+ | :-( | fannkuch| 0.252% | -1.892% | +4.238% | +5.302% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.995% | +0.465% | +1.749% | +8.279% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.478% | +0.998% | +12.776% | +9.958% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.456% | -0.245% | +8.377% | +9.701% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.846% | +0.294% | +6.193% | +11.749% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.680% | -0.050% | +10.327% | +11.004% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.030% | -3.203% | +5.758% | +10.053% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.734% | -0.033% | +1.535% | +10.066% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 3.959% | +5.068% | +0.710% | +12.779% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.211% | +0.663% | +7.887% | +11.376% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.802% | +0.509% | +47.028% | +12.417% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.883% | +1.902% | +8.362% | +13.178% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.322% | +0.158% | +17.328% | +13.353% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.516% | +1.555% | +11.192% | +5.704% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.693% | -0.647% | +2.987% | +6.466% | +-----+------------------------+--------+------------+------------+------------+ | :-( | nbody| 0.565% | -2.586% | -3.045% | +3.650% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.622% | +0.145% | +3.932% | +8.854% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 0.861% | +1.644% | +3.033% | +12.137% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.338% | +1.763% | +1.479% | +19.814% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.841% | -1.285% | +1.010% | +19.080% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.655% | -1.584% | +1.795% | +19.251% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 2.850% | -1.032% | +10.086% | +11.351% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.063% | -0.187% | +0.109% | +10.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.132% | +0.288% | +10.232% | +5.078% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.116% | +0.586% | +1.570% | +5.037% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.055% | -0.063% | +9.753% | +14.194% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.778% | +2.190% | +5.421% | +9.460% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.528% | +1.391% | -0.921% | +9.515% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.254% | +1.477% | -4.529% | +1.618% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 0.919% | -0.445% | +3.886% | +6.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.440% | -1.416% | +6.982% | +17.018% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.633% | -0.351% | -3.787% | +4.554% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.631% | +0.159% | +26.770% | +8.360% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.542% | +0.194% | +2.314% | +6.283% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 2.428% | -0.582% | +13.155% | +10.064% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.430% | -1.508% | -6.797% | -4.037% | +-----+------------------------+--------+------------+------------+------------+ | :-( | spectral_norm| 0.549% | -8.153% | -2.486% | +8.448% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.330% | -0.252% | +6.564% | +6.342% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.215% | -0.686% | +6.018% | +4.705% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.563% | +4.805% | +20.864% | +4.966% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.077% | +1.234% | +12.488% | +6.640% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.680% | +0.942% | +9.364% | +5.798% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.732% | +0.333% | +11.373% | +7.706% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.202% | -0.502% | +9.671% | +9.266% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.177% | +0.087% | +18.302% | +13.514% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.110% | -0.071% | +5.543% | +4.629% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.685% | -0.110% | +1.910% | +1.091% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 5.941% | +1.413% | +5.954% | +21.827% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 2.237% | -3.466% | -6.876% | +22.429% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.982% | -0.757% | +6.750% | +7.346% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.056% | +1.457% | +5.294% | +9.354% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.415% | +0.435% | +2.628% | +8.324% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.551% | +1.873% | -8.727% | +14.749% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.246% | +1.337% | +6.732% | +9.491% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/4-down-61-flat-results-for-python-master-branch-2017-12-20 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu Dec 21 00:33:57 2017 From: webhook-mailer at python.org (Alexander Belopolsky) Date: Thu, 21 Dec 2017 05:33:57 -0000 Subject: [Python-checkins] bpo-15873: Implement [date][time].fromisoformat (#4699) Message-ID: https://github.com/python/cpython/commit/09dc2f508c8513e0466a759cc27a09108c1e55c2 commit: 09dc2f508c8513e0466a759cc27a09108c1e55c2 branch: master author: Paul Ganssle committer: Alexander Belopolsky date: 2017-12-21T00:33:49-05:00 summary: bpo-15873: Implement [date][time].fromisoformat (#4699) Closes bpo-15873. files: A Misc/NEWS.d/next/Library/2017-12-04-17-41-40.bpo-15873.-T4TRK.rst M Doc/library/datetime.rst M Lib/datetime.py M Lib/test/datetimetester.py M Modules/_datetimemodule.c diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index dce51a16e86..c1b164ebc1f 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -436,6 +436,21 @@ Other constructors, all class methods: d``. +.. classmethod:: date.fromisoformat(date_string) + + Return a :class:`date` corresponding to a *date_string* in the format emitted + by :meth:`date.isoformat`. Specifically, this function supports strings in + the format(s) ``YYYY-MM-DD``. + + .. caution:: + + This does not support parsing arbitrary ISO 8601 strings - it is only intended + as the inverse operation of :meth:`date.isoformat`. + + .. versionadded:: 3.7 + + + Class attributes: .. attribute:: date.min @@ -819,6 +834,21 @@ Other constructors, all class methods: Added the *tzinfo* argument. +.. classmethod:: datetime.fromisoformat(date_string) + + Return a :class:`datetime` corresponding to a *date_string* in one of the + formats emitted by :meth:`date.isoformat` and :meth:`datetime.isoformat`. + Specifically, this function supports strings in the format(s) + ``YYYY-MM-DD[*HH[:MM[:SS[.mmm[mmm]]]][+HH:MM[:SS[.ffffff]]]]``, + where ``*`` can match any single character. + + .. caution:: + + This does not support parsing arbitrary ISO 8601 strings - it is only intended + as the inverse operation of :meth:`datetime.isoformat`. + + .. versionadded:: 3.7 + .. classmethod:: datetime.strptime(date_string, format) Return a :class:`.datetime` corresponding to *date_string*, parsed according to @@ -1486,6 +1516,23 @@ In boolean contexts, a :class:`.time` object is always considered to be true. error-prone and has been removed in Python 3.5. See :issue:`13936` for full details. + +Other constructor: + +.. classmethod:: time.fromisoformat(time_string) + + Return a :class:`time` corresponding to a *time_string* in one of the + formats emitted by :meth:`time.isoformat`. Specifically, this function supports + strings in the format(s) ``HH[:MM[:SS[.mmm[mmm]]]][+HH:MM[:SS[.ffffff]]]``. + + .. caution:: + + This does not support parsing arbitrary ISO 8601 strings - it is only intended + as the inverse operation of :meth:`time.isoformat`. + + .. versionadded:: 3.7 + + Instance methods: .. method:: time.replace(hour=self.hour, minute=self.minute, second=self.second, \ @@ -1587,7 +1634,6 @@ Instance methods: ``self.tzinfo.tzname(None)``, or raises an exception if the latter doesn't return ``None`` or a string object. - Example: >>> from datetime import time, tzinfo, timedelta diff --git a/Lib/datetime.py b/Lib/datetime.py index 67d8600921c..8fa18a78932 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -173,6 +173,24 @@ def _format_time(hh, mm, ss, us, timespec='auto'): else: return fmt.format(hh, mm, ss, us) +def _format_offset(off): + s = '' + if off is not None: + if off.days < 0: + sign = "-" + off = -off + else: + sign = "+" + hh, mm = divmod(off, timedelta(hours=1)) + mm, ss = divmod(mm, timedelta(minutes=1)) + s += "%s%02d:%02d" % (sign, hh, mm) + if ss or ss.microseconds: + s += ":%02d" % ss.seconds + + if ss.microseconds: + s += '.%06d' % ss.microseconds + return s + # Correctly substitute for %z and %Z escapes in strftime formats. def _wrap_strftime(object, format, timetuple): # Don't call utcoffset() or tzname() unless actually needed. @@ -237,6 +255,102 @@ def _wrap_strftime(object, format, timetuple): newformat = "".join(newformat) return _time.strftime(newformat, timetuple) +# Helpers for parsing the result of isoformat() +def _parse_isoformat_date(dtstr): + # It is assumed that this function will only be called with a + # string of length exactly 10, and (though this is not used) ASCII-only + year = int(dtstr[0:4]) + if dtstr[4] != '-': + raise ValueError('Invalid date separator: %s' % dtstr[4]) + + month = int(dtstr[5:7]) + + if dtstr[7] != '-': + raise ValueError('Invalid date separator') + + day = int(dtstr[8:10]) + + return [year, month, day] + +def _parse_hh_mm_ss_ff(tstr): + # Parses things of the form HH[:MM[:SS[.fff[fff]]]] + len_str = len(tstr) + + time_comps = [0, 0, 0, 0] + pos = 0 + for comp in range(0, 3): + if (len_str - pos) < 2: + raise ValueError('Incomplete time component') + + time_comps[comp] = int(tstr[pos:pos+2]) + + pos += 2 + next_char = tstr[pos:pos+1] + + if not next_char or comp >= 2: + break + + if next_char != ':': + raise ValueError('Invalid time separator: %c' % next_char) + + pos += 1 + + if pos < len_str: + if tstr[pos] != '.': + raise ValueError('Invalid microsecond component') + else: + pos += 1 + + len_remainder = len_str - pos + if len_remainder not in (3, 6): + raise ValueError('Invalid microsecond component') + + time_comps[3] = int(tstr[pos:]) + if len_remainder == 3: + time_comps[3] *= 1000 + + return time_comps + +def _parse_isoformat_time(tstr): + # Format supported is HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]] + len_str = len(tstr) + if len_str < 2: + raise ValueError('Isoformat time too short') + + # This is equivalent to re.search('[+-]', tstr), but faster + tz_pos = (tstr.find('-') + 1 or tstr.find('+') + 1) + timestr = tstr[:tz_pos-1] if tz_pos > 0 else tstr + + time_comps = _parse_hh_mm_ss_ff(timestr) + + tzi = None + if tz_pos > 0: + tzstr = tstr[tz_pos:] + + # Valid time zone strings are: + # HH:MM len: 5 + # HH:MM:SS len: 8 + # HH:MM:SS.ffffff len: 15 + + if len(tzstr) not in (5, 8, 15): + raise ValueError('Malformed time zone string') + + tz_comps = _parse_hh_mm_ss_ff(tzstr) + if all(x == 0 for x in tz_comps): + tzi = timezone.utc + else: + tzsign = -1 if tstr[tz_pos - 1] == '-' else 1 + + td = timedelta(hours=tz_comps[0], minutes=tz_comps[1], + seconds=tz_comps[2], microseconds=tz_comps[3]) + + tzi = timezone(tzsign * td) + + time_comps.append(tzi) + + return time_comps + + # Just raise TypeError if the arg isn't None or a string. def _check_tzname(name): if name is not None and not isinstance(name, str): @@ -732,6 +846,19 @@ def fromordinal(cls, n): y, m, d = _ord2ymd(n) return cls(y, m, d) + @classmethod + def fromisoformat(cls, date_string): + """Construct a date from the output of date.isoformat().""" + if not isinstance(date_string, str): + raise TypeError('fromisoformat: argument must be str') + + try: + assert len(date_string) == 10 + return cls(*_parse_isoformat_date(date_string)) + except Exception: + raise ValueError('Invalid isoformat string: %s' % date_string) + + # Conversions to string def __repr__(self): @@ -1190,22 +1317,10 @@ def __hash__(self): # Conversion to string - def _tzstr(self, sep=":"): - """Return formatted timezone offset (+xx:xx) or None.""" + def _tzstr(self): + """Return formatted timezone offset (+xx:xx) or an empty string.""" off = self.utcoffset() - if off is not None: - if off.days < 0: - sign = "-" - off = -off - else: - sign = "+" - hh, mm = divmod(off, timedelta(hours=1)) - mm, ss = divmod(mm, timedelta(minutes=1)) - assert 0 <= hh < 24 - off = "%s%02d%s%02d" % (sign, hh, sep, mm) - if ss: - off += ':%02d' % ss.seconds - return off + return _format_offset(off) def __repr__(self): """Convert to formal string, for repr().""" @@ -1244,6 +1359,18 @@ def isoformat(self, timespec='auto'): __str__ = isoformat + @classmethod + def fromisoformat(cls, time_string): + """Construct a time from the output of isoformat().""" + if not isinstance(time_string, str): + raise TypeError('fromisoformat: argument must be str') + + try: + return cls(*_parse_isoformat_time(time_string)) + except Exception: + raise ValueError('Invalid isoformat string: %s' % time_string) + + def strftime(self, fmt): """Format using strftime(). The date part of the timestamp passed to underlying strftime should not be used. @@ -1497,6 +1624,31 @@ def combine(cls, date, time, tzinfo=True): time.hour, time.minute, time.second, time.microsecond, tzinfo, fold=time.fold) + @classmethod + def fromisoformat(cls, date_string): + """Construct a datetime from the output of datetime.isoformat().""" + if not isinstance(date_string, str): + raise TypeError('fromisoformat: argument must be str') + + # Split this at the separator + dstr = date_string[0:10] + tstr = date_string[11:] + + try: + date_components = _parse_isoformat_date(dstr) + except ValueError: + raise ValueError('Invalid isoformat string: %s' % date_string) + + if tstr: + try: + time_components = _parse_isoformat_time(tstr) + except ValueError: + raise ValueError('Invalid isoformat string: %s' % date_string) + else: + time_components = [0, 0, 0, 0, None] + + return cls(*(date_components + time_components)) + def timetuple(self): "Return local time tuple compatible with time.localtime()." dst = self.dst() @@ -1673,18 +1825,10 @@ def isoformat(self, sep='T', timespec='auto'): self._microsecond, timespec)) off = self.utcoffset() - if off is not None: - if off.days < 0: - sign = "-" - off = -off - else: - sign = "+" - hh, mm = divmod(off, timedelta(hours=1)) - mm, ss = divmod(mm, timedelta(minutes=1)) - s += "%s%02d:%02d" % (sign, hh, mm) - if ss: - assert not ss.microseconds - s += ":%02d" % ss.seconds + tz = _format_offset(off) + if tz: + s += tz + return s def __repr__(self): @@ -2275,9 +2419,10 @@ def _name_from_offset(delta): _check_date_fields, _check_int_field, _check_time_fields, _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror, _date_class, _days_before_month, _days_before_year, _days_in_month, - _format_time, _is_leap, _isoweek1monday, _math, _ord2ymd, - _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord, - _divide_and_round) + _format_time, _format_offset, _is_leap, _isoweek1monday, _math, + _ord2ymd, _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord, + _divide_and_round, _parse_isoformat_date, _parse_isoformat_time, + _parse_hh_mm_ss_ff) # XXX Since import * above excludes names that start with _, # docstring does not get overwritten. In the future, it may be # appropriate to maintain a single module level docstring and diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index d0886c47bae..1d0c1c5bd23 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -49,7 +49,6 @@ INF = float("inf") NAN = float("nan") - ############################################################################# # module tests @@ -1588,6 +1587,63 @@ def test_backdoor_resistance(self): # blow up because other fields are insane. self.theclass(base[:2] + bytes([ord_byte]) + base[3:]) + def test_fromisoformat(self): + # Test that isoformat() is reversible + base_dates = [ + (1, 1, 1), + (1000, 2, 14), + (1900, 1, 1), + (2000, 2, 29), + (2004, 11, 12), + (2004, 4, 3), + (2017, 5, 30) + ] + + for dt_tuple in base_dates: + dt = self.theclass(*dt_tuple) + dt_str = dt.isoformat() + with self.subTest(dt_str=dt_str): + dt_rt = self.theclass.fromisoformat(dt.isoformat()) + + self.assertEqual(dt, dt_rt) + + def test_fromisoformat_subclass(self): + class DateSubclass(self.theclass): + pass + + dt = DateSubclass(2014, 12, 14) + + dt_rt = DateSubclass.fromisoformat(dt.isoformat()) + + self.assertIsInstance(dt_rt, DateSubclass) + + def test_fromisoformat_fails(self): + # Test that fromisoformat() fails on invalid values + bad_strs = [ + '', # Empty string + '009-03-04', # Not 10 characters + '123456789', # Not a date + '200a-12-04', # Invalid character in year + '2009-1a-04', # Invalid character in month + '2009-12-0a', # Invalid character in day + '2009-01-32', # Invalid day + '2009-02-29', # Invalid leap day + '20090228', # Valid ISO8601 output not from isoformat() + ] + + for bad_str in bad_strs: + with self.assertRaises(ValueError): + self.theclass.fromisoformat(bad_str) + + def test_fromisoformat_fails_typeerror(self): + # Test that fromisoformat fails when passed the wrong type + import io + + bad_types = [b'2009-03-01', None, io.StringIO('2009-03-01')] + for bad_type in bad_types: + with self.assertRaises(TypeError): + self.theclass.fromisoformat(bad_type) + ############################################################################# # datetime tests @@ -1675,6 +1731,36 @@ def test_isoformat(self): t = self.theclass(2, 3, 2, tzinfo=tz) self.assertEqual(t.isoformat(), "0002-03-02T00:00:00+00:00:16") + def test_isoformat_timezone(self): + tzoffsets = [ + ('05:00', timedelta(hours=5)), + ('02:00', timedelta(hours=2)), + ('06:27', timedelta(hours=6, minutes=27)), + ('12:32:30', timedelta(hours=12, minutes=32, seconds=30)), + ('02:04:09.123456', timedelta(hours=2, minutes=4, seconds=9, microseconds=123456)) + ] + + tzinfos = [ + ('', None), + ('+00:00', timezone.utc), + ('+00:00', timezone(timedelta(0))), + ] + + tzinfos += [ + (prefix + expected, timezone(sign * td)) + for expected, td in tzoffsets + for prefix, sign in [('-', -1), ('+', 1)] + ] + + dt_base = self.theclass(2016, 4, 1, 12, 37, 9) + exp_base = '2016-04-01T12:37:09' + + for exp_tz, tzi in tzinfos: + dt = dt_base.replace(tzinfo=tzi) + exp = exp_base + exp_tz + with self.subTest(tzi=tzi): + assert dt.isoformat() == exp + def test_format(self): dt = self.theclass(2007, 9, 10, 4, 5, 1, 123) self.assertEqual(dt.__format__(''), str(dt)) @@ -2334,6 +2420,173 @@ def newmeth(self, start): self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month + dt1.second - 7) + def test_fromisoformat_datetime(self): + # Test that isoformat() is reversible + base_dates = [ + (1, 1, 1), + (1900, 1, 1), + (2004, 11, 12), + (2017, 5, 30) + ] + + base_times = [ + (0, 0, 0, 0), + (0, 0, 0, 241000), + (0, 0, 0, 234567), + (12, 30, 45, 234567) + ] + + separators = [' ', 'T'] + + tzinfos = [None, timezone.utc, + timezone(timedelta(hours=-5)), + timezone(timedelta(hours=2))] + + dts = [self.theclass(*date_tuple, *time_tuple, tzinfo=tzi) + for date_tuple in base_dates + for time_tuple in base_times + for tzi in tzinfos] + + for dt in dts: + for sep in separators: + dtstr = dt.isoformat(sep=sep) + + with self.subTest(dtstr=dtstr): + dt_rt = self.theclass.fromisoformat(dtstr) + self.assertEqual(dt, dt_rt) + + def test_fromisoformat_timezone(self): + base_dt = self.theclass(2014, 12, 30, 12, 30, 45, 217456) + + tzoffsets = [ + timedelta(hours=5), timedelta(hours=2), + timedelta(hours=6, minutes=27), + timedelta(hours=12, minutes=32, seconds=30), + timedelta(hours=2, minutes=4, seconds=9, microseconds=123456) + ] + + tzoffsets += [-1 * td for td in tzoffsets] + + tzinfos = [None, timezone.utc, + timezone(timedelta(hours=0))] + + tzinfos += [timezone(td) for td in tzoffsets] + + for tzi in tzinfos: + dt = base_dt.replace(tzinfo=tzi) + dtstr = dt.isoformat() + + with self.subTest(tstr=dtstr): + dt_rt = self.theclass.fromisoformat(dtstr) + assert dt == dt_rt, dt_rt + + def test_fromisoformat_separators(self): + separators = [ + ' ', 'T', '\u007f', # 1-bit widths + '\u0080', '?', # 2-bit widths + '?', '?', # 3-bit widths + '?' # 4-bit widths + ] + + for sep in separators: + dt = self.theclass(2018, 1, 31, 23, 59, 47, 124789) + dtstr = dt.isoformat(sep=sep) + + with self.subTest(dtstr=dtstr): + dt_rt = self.theclass.fromisoformat(dtstr) + self.assertEqual(dt, dt_rt) + + def test_fromisoformat_ambiguous(self): + # Test strings like 2018-01-31+12:15 (where +12:15 is not a time zone) + separators = ['+', '-'] + for sep in separators: + dt = self.theclass(2018, 1, 31, 12, 15) + dtstr = dt.isoformat(sep=sep) + + with self.subTest(dtstr=dtstr): + dt_rt = self.theclass.fromisoformat(dtstr) + self.assertEqual(dt, dt_rt) + + def test_fromisoformat_timespecs(self): + datetime_bases = [ + (2009, 12, 4, 8, 17, 45, 123456), + (2009, 12, 4, 8, 17, 45, 0)] + + tzinfos = [None, timezone.utc, + timezone(timedelta(hours=-5)), + timezone(timedelta(hours=2)), + timezone(timedelta(hours=6, minutes=27))] + + timespecs = ['hours', 'minutes', 'seconds', + 'milliseconds', 'microseconds'] + + for ip, ts in enumerate(timespecs): + for tzi in tzinfos: + for dt_tuple in datetime_bases: + if ts == 'milliseconds': + new_microseconds = 1000 * (dt_tuple[6] // 1000) + dt_tuple = dt_tuple[0:6] + (new_microseconds,) + + dt = self.theclass(*(dt_tuple[0:(4 + ip)]), tzinfo=tzi) + dtstr = dt.isoformat(timespec=ts) + with self.subTest(dtstr=dtstr): + dt_rt = self.theclass.fromisoformat(dtstr) + self.assertEqual(dt, dt_rt) + + def test_fromisoformat_fails_datetime(self): + # Test that fromisoformat() fails on invalid values + bad_strs = [ + '', # Empty string + '2009.04-19T03', # Wrong first separator + '2009-04.19T03', # Wrong second separator + '2009-04-19T0a', # Invalid hours + '2009-04-19T03:1a:45', # Invalid minutes + '2009-04-19T03:15:4a', # Invalid seconds + '2009-04-19T03;15:45', # Bad first time separator + '2009-04-19T03:15;45', # Bad second time separator + '2009-04-19T03:15:4500:00', # Bad time zone separator + '2009-04-19T03:15:45.2345', # Too many digits for milliseconds + '2009-04-19T03:15:45.1234567', # Too many digits for microseconds + '2009-04-19T03:15:45.123456+24:30', # Invalid time zone offset + '2009-04-19T03:15:45.123456-24:30', # Invalid negative offset + '2009-04-10?????12:15', # Too many unicode separators + '2009-04-19T1', # Incomplete hours + '2009-04-19T12:3', # Incomplete minutes + '2009-04-19T12:30:4', # Incomplete seconds + '2009-04-19T12:', # Ends with time separator + '2009-04-19T12:30:', # Ends with time separator + '2009-04-19T12:30:45.', # Ends with time separator + '2009-04-19T12:30:45.123456+', # Ends with timzone separator + '2009-04-19T12:30:45.123456-', # Ends with timzone separator + '2009-04-19T12:30:45.123456-05:00a', # Extra text + '2009-04-19T12:30:45.123-05:00a', # Extra text + '2009-04-19T12:30:45-05:00a', # Extra text + ] + + for bad_str in bad_strs: + with self.subTest(bad_str=bad_str): + with self.assertRaises(ValueError): + self.theclass.fromisoformat(bad_str) + + def test_fromisoformat_utc(self): + dt_str = '2014-04-19T13:21:13+00:00' + dt = self.theclass.fromisoformat(dt_str) + + self.assertIs(dt.tzinfo, timezone.utc) + + def test_fromisoformat_subclass(self): + class DateTimeSubclass(self.theclass): + pass + + dt = DateTimeSubclass(2014, 12, 14, 9, 30, 45, 457390, + tzinfo=timezone(timedelta(hours=10, minutes=45))) + + dt_rt = DateTimeSubclass.fromisoformat(dt.isoformat()) + + self.assertEqual(dt, dt_rt) + self.assertIsInstance(dt_rt, DateTimeSubclass) + + class TestSubclassDateTime(TestDateTime): theclass = SubclassDatetime # Override tests not designed for subclass @@ -2517,6 +2770,36 @@ def test_isoformat(self): self.assertEqual(t.isoformat(timespec='microseconds'), "12:34:56.000000") self.assertEqual(t.isoformat(timespec='auto'), "12:34:56") + def test_isoformat_timezone(self): + tzoffsets = [ + ('05:00', timedelta(hours=5)), + ('02:00', timedelta(hours=2)), + ('06:27', timedelta(hours=6, minutes=27)), + ('12:32:30', timedelta(hours=12, minutes=32, seconds=30)), + ('02:04:09.123456', timedelta(hours=2, minutes=4, seconds=9, microseconds=123456)) + ] + + tzinfos = [ + ('', None), + ('+00:00', timezone.utc), + ('+00:00', timezone(timedelta(0))), + ] + + tzinfos += [ + (prefix + expected, timezone(sign * td)) + for expected, td in tzoffsets + for prefix, sign in [('-', -1), ('+', 1)] + ] + + t_base = self.theclass(12, 37, 9) + exp_base = '12:37:09' + + for exp_tz, tzi in tzinfos: + t = t_base.replace(tzinfo=tzi) + exp = exp_base + exp_tz + with self.subTest(tzi=tzi): + assert t.isoformat() == exp + def test_1653736(self): # verify it doesn't accept extra keyword arguments t = self.theclass(second=1) @@ -3055,6 +3338,133 @@ def utcoffset(self, t): t2 = t2.replace(tzinfo=Varies()) self.assertTrue(t1 < t2) # t1's offset counter still going up + def test_fromisoformat(self): + time_examples = [ + (0, 0, 0, 0), + (23, 59, 59, 999999), + ] + + hh = (9, 12, 20) + mm = (5, 30) + ss = (4, 45) + usec = (0, 245000, 678901) + + time_examples += list(itertools.product(hh, mm, ss, usec)) + + tzinfos = [None, timezone.utc, + timezone(timedelta(hours=2)), + timezone(timedelta(hours=6, minutes=27))] + + for ttup in time_examples: + for tzi in tzinfos: + t = self.theclass(*ttup, tzinfo=tzi) + tstr = t.isoformat() + + with self.subTest(tstr=tstr): + t_rt = self.theclass.fromisoformat(tstr) + self.assertEqual(t, t_rt) + + def test_fromisoformat_timezone(self): + base_time = self.theclass(12, 30, 45, 217456) + + tzoffsets = [ + timedelta(hours=5), timedelta(hours=2), + timedelta(hours=6, minutes=27), + timedelta(hours=12, minutes=32, seconds=30), + timedelta(hours=2, minutes=4, seconds=9, microseconds=123456) + ] + + tzoffsets += [-1 * td for td in tzoffsets] + + tzinfos = [None, timezone.utc, + timezone(timedelta(hours=0))] + + tzinfos += [timezone(td) for td in tzoffsets] + + for tzi in tzinfos: + t = base_time.replace(tzinfo=tzi) + tstr = t.isoformat() + + with self.subTest(tstr=tstr): + t_rt = self.theclass.fromisoformat(tstr) + assert t == t_rt, t_rt + + def test_fromisoformat_timespecs(self): + time_bases = [ + (8, 17, 45, 123456), + (8, 17, 45, 0) + ] + + tzinfos = [None, timezone.utc, + timezone(timedelta(hours=-5)), + timezone(timedelta(hours=2)), + timezone(timedelta(hours=6, minutes=27))] + + timespecs = ['hours', 'minutes', 'seconds', + 'milliseconds', 'microseconds'] + + for ip, ts in enumerate(timespecs): + for tzi in tzinfos: + for t_tuple in time_bases: + if ts == 'milliseconds': + new_microseconds = 1000 * (t_tuple[-1] // 1000) + t_tuple = t_tuple[0:-1] + (new_microseconds,) + + t = self.theclass(*(t_tuple[0:(1 + ip)]), tzinfo=tzi) + tstr = t.isoformat(timespec=ts) + with self.subTest(tstr=tstr): + t_rt = self.theclass.fromisoformat(tstr) + self.assertEqual(t, t_rt) + + def test_fromisoformat_fails(self): + bad_strs = [ + '', # Empty string + '12:', # Ends on a separator + '12:30:', # Ends on a separator + '12:30:15.', # Ends on a separator + '1', # Incomplete hours + '12:3', # Incomplete minutes + '12:30:1', # Incomplete seconds + '1a:30:45.334034', # Invalid character in hours + '12:a0:45.334034', # Invalid character in minutes + '12:30:a5.334034', # Invalid character in seconds + '12:30:45.1234', # Too many digits for milliseconds + '12:30:45.1234567', # Too many digits for microseconds + '12:30:45.123456+24:30', # Invalid time zone offset + '12:30:45.123456-24:30', # Invalid negative offset + '12?30?45', # Uses full-width unicode colons + '12:30:45?123456', # Uses \u2024 in place of decimal point + '12:30:45a', # Extra at tend of basic time + '12:30:45.123a', # Extra at end of millisecond time + '12:30:45.123456a', # Extra at end of microsecond time + '12:30:45.123456+12:00:30a', # Extra at end of full time + ] + + for bad_str in bad_strs: + with self.subTest(bad_str=bad_str): + with self.assertRaises(ValueError): + self.theclass.fromisoformat(bad_str) + + def test_fromisoformat_fails_typeerror(self): + # Test the fromisoformat fails when passed the wrong type + import io + + bad_types = [b'12:30:45', None, io.StringIO('12:30:45')] + + for bad_type in bad_types: + with self.assertRaises(TypeError): + self.theclass.fromisoformat(bad_type) + + def test_fromisoformat_subclass(self): + class TimeSubclass(self.theclass): + pass + + tsc = TimeSubclass(12, 14, 45, 203745, tzinfo=timezone.utc) + tsc_rt = TimeSubclass.fromisoformat(tsc.isoformat()) + + self.assertEqual(tsc, tsc_rt) + self.assertIsInstance(tsc_rt, TimeSubclass) + def test_subclass_timetz(self): class C(self.theclass): diff --git a/Misc/NEWS.d/next/Library/2017-12-04-17-41-40.bpo-15873.-T4TRK.rst b/Misc/NEWS.d/next/Library/2017-12-04-17-41-40.bpo-15873.-T4TRK.rst new file mode 100644 index 00000000000..98a841597af --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-04-17-41-40.bpo-15873.-T4TRK.rst @@ -0,0 +1,3 @@ +Added new alternate constructors :meth:`datetime.datetime.fromisoformat`, +:meth:`datetime.time.fromisoformat` and :meth:`datetime.date.fromisoformat` +as the inverse operation of each classes's respective ``isoformat`` methods. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index b50cddad5dd..624196702b6 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -663,6 +663,167 @@ set_date_fields(PyDateTime_Date *self, int y, int m, int d) SET_DAY(self, d); } +/* --------------------------------------------------------------------------- + * String parsing utilities and helper functions + */ + +static const char* +parse_digits(const char* ptr, int* var, size_t num_digits) +{ + for (size_t i = 0; i < num_digits; ++i) { + unsigned int tmp = (unsigned int)(*(ptr++) - '0'); + if (tmp > 9) { + return NULL; + } + *var *= 10; + *var += (signed int)tmp; + } + + return ptr; +} + +static int parse_isoformat_date(const char *dtstr, + int* year, int *month, int* day) { + /* Parse the date components of the result of date.isoformat() + * + * Return codes: + * 0: Success + * -1: Failed to parse date component + * -2: Failed to parse dateseparator + */ + const char *p = dtstr; + p = parse_digits(p, year, 4); + if (NULL == p) { + return -1; + } + + if (*(p++) != '-') { + return -2; + } + + p = parse_digits(p, month, 2); + if (NULL == p) { + return -1; + } + + if (*(p++) != '-') { + return -2; + } + + p = parse_digits(p, day, 2); + if (p == NULL) { + return -1; + } + + return 0; +} + +static int +parse_hh_mm_ss_ff(const char *tstr, const char *tstr_end, + int* hour, int* minute, int *second, int *microsecond) { + const char *p = tstr; + const char *p_end = tstr_end; + int *vals[3] = {hour, minute, second}; + + // Parse [HH[:MM[:SS]]] + for (size_t i = 0; i < 3; ++i) { + p = parse_digits(p, vals[i], 2); + if (NULL == p) { + return -3; + } + + char c = *(p++); + if (p >= p_end) { + return c != '\0'; + } else if (c == ':') { + continue; + } else if (c == '.') { + break; + } else { + return -4; // Malformed time separator + } + } + + // Parse .fff[fff] + size_t len_remains = p_end - p; + if (!(len_remains == 6 || len_remains == 3)) { + return -3; + } + + p = parse_digits(p, microsecond, len_remains); + if (NULL == p) { + return -3; + } + + if (len_remains == 3) { + *microsecond *= 1000; + } + + // Return 1 if it's not the end of the string + return *p != '\0'; +} + +static int +parse_isoformat_time(const char *dtstr, size_t dtlen, + int* hour, int *minute, int *second, int *microsecond, + int* tzoffset, int *tzmicrosecond) { + // Parse the time portion of a datetime.isoformat() string + // + // Return codes: + // 0: Success (no tzoffset) + // 1: Success (with tzoffset) + // -3: Failed to parse time component + // -4: Failed to parse time separator + // -5: Malformed timezone string + + const char *p = dtstr; + const char *p_end = dtstr + dtlen; + + const char *tzinfo_pos = p; + do { + if (*tzinfo_pos == '+' || *tzinfo_pos == '-') { + break; + } + } while(++tzinfo_pos < p_end); + + int rv = parse_hh_mm_ss_ff(dtstr, tzinfo_pos, + hour, minute, second, microsecond); + + if (rv < 0) { + return rv; + } else if (tzinfo_pos == p_end) { + // We know that there's no time zone, so if there's stuff at the + // end of the string it's an error. + if (rv == 1) { + return -5; + } else { + return 0; + } + } + + // Parse time zone component + // Valid formats are: + // - +HH:MM (len 6) + // - +HH:MM:SS (len 9) + // - +HH:MM:SS.ffffff (len 16) + size_t tzlen = p_end - tzinfo_pos; + if (!(tzlen == 6 || tzlen == 9 || tzlen == 16)) { + return -5; + } + + int tzsign = (*tzinfo_pos == '-')?-1:1; + tzinfo_pos++; + int tzhour = 0, tzminute = 0, tzsecond = 0; + rv = parse_hh_mm_ss_ff(tzinfo_pos, p_end, + &tzhour, &tzminute, &tzsecond, tzmicrosecond); + + *tzoffset = tzsign * ((tzhour * 3600) + (tzminute * 60) + tzsecond); + *tzmicrosecond *= tzsign; + + return rv?-5:1; +} + + /* --------------------------------------------------------------------------- * Create various objects, mostly without range checking. */ @@ -1063,6 +1224,27 @@ append_keyword_fold(PyObject *repr, int fold) return repr; } +static inline PyObject * +tzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds) { + PyObject *tzinfo; + if (rv == 1) { + // Create a timezone from offset in seconds (0 returns UTC) + if (tzoffset == 0) { + Py_INCREF(PyDateTime_TimeZone_UTC); + return PyDateTime_TimeZone_UTC; + } + + PyObject *delta = new_delta(0, tzoffset, tz_useconds, 1); + tzinfo = new_timezone(delta, NULL); + Py_XDECREF(delta); + } else { + tzinfo = Py_None; + Py_INCREF(Py_None); + } + + return tzinfo; +} + /* --------------------------------------------------------------------------- * String format helpers. */ @@ -2607,6 +2789,7 @@ date_fromtimestamp(PyObject *cls, PyObject *args) return result; } + /* Return new date from proleptic Gregorian ordinal. Raises ValueError if * the ordinal is out of range. */ @@ -2633,6 +2816,46 @@ date_fromordinal(PyObject *cls, PyObject *args) return result; } +/* Return the new date from a string as generated by date.isoformat() */ +static PyObject * +date_fromisoformat(PyObject *cls, PyObject *dtstr) { + assert(dtstr != NULL); + + if (!PyUnicode_Check(dtstr)) { + PyErr_SetString(PyExc_TypeError, "fromisoformat: argument must be str"); + return NULL; + } + + Py_ssize_t len; + + const char * dt_ptr = PyUnicode_AsUTF8AndSize(dtstr, &len); + + int year = 0, month = 0, day = 0; + + int rv; + if (len == 10) { + rv = parse_isoformat_date(dt_ptr, &year, &month, &day); + } else { + rv = -1; + } + + if (rv < 0) { + PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %s", + dt_ptr); + return NULL; + } + + PyObject *result; + if ( (PyTypeObject*)cls == &PyDateTime_DateType ) { + result = new_date_ex(year, month, day, (PyTypeObject*)cls); + } else { + result = PyObject_CallFunction(cls, "iii", year, month, day); + } + + return result; +} + + /* * Date arithmetic. */ @@ -2925,6 +3148,10 @@ static PyMethodDef date_methods[] = { PyDoc_STR("int -> date corresponding to a proleptic Gregorian " "ordinal.")}, + {"fromisoformat", (PyCFunction)date_fromisoformat, METH_O | + METH_CLASS, + PyDoc_STR("str -> Construct a date from the output of date.isoformat()")}, + {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS, PyDoc_STR("Current date or datetime: same as " "self.__class__.fromtimestamp(time.time()).")}, @@ -3972,6 +4199,49 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw) return clone; } +static PyObject * +time_fromisoformat(PyObject *cls, PyObject *tstr) { + assert(tstr != NULL); + + if (!PyUnicode_Check(tstr)) { + PyErr_SetString(PyExc_TypeError, "fromisoformat: argument must be str"); + return NULL; + } + + Py_ssize_t len; + const char *p = PyUnicode_AsUTF8AndSize(tstr, &len); + + int hour = 0, minute = 0, second = 0, microsecond = 0; + int tzoffset, tzimicrosecond = 0; + int rv = parse_isoformat_time(p, len, + &hour, &minute, &second, µsecond, + &tzoffset, &tzimicrosecond); + + if (rv < 0) { + PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %s", p); + return NULL; + } + + PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, + tzimicrosecond); + + if (tzinfo == NULL) { + return NULL; + } + + PyObject *t; + if ( (PyTypeObject *)cls == &PyDateTime_TimeType ) { + t = new_time(hour, minute, second, microsecond, tzinfo, 0); + } else { + t = PyObject_CallFunction(cls, "iiiiO", + hour, minute, second, microsecond, tzinfo); + } + + Py_DECREF(tzinfo); + return t; +} + + /* Pickle support, a simple use of __reduce__. */ /* Let basestate be the non-tzinfo data string. @@ -4041,6 +4311,9 @@ static PyMethodDef time_methods[] = { {"replace", (PyCFunction)time_replace, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("Return time with new specified fields.")}, + {"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS, + PyDoc_STR("string -> time from time.isoformat() output")}, + {"__reduce_ex__", (PyCFunction)time_reduce_ex, METH_VARARGS, PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")}, @@ -4506,6 +4779,82 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw) return result; } +static PyObject * +datetime_fromisoformat(PyObject* cls, PyObject *dtstr) { + assert(dtstr != NULL); + + if (!PyUnicode_Check(dtstr)) { + PyErr_SetString(PyExc_TypeError, "fromisoformat: argument must be str"); + return NULL; + } + + Py_ssize_t len; + const char * dt_ptr = PyUnicode_AsUTF8AndSize(dtstr, &len); + const char * p = dt_ptr; + + int year = 0, month = 0, day = 0; + int hour = 0, minute = 0, second = 0, microsecond = 0; + int tzoffset = 0, tzusec = 0; + + // date has a fixed length of 10 + int rv = parse_isoformat_date(p, &year, &month, &day); + + if (!rv && len > 10) { + // In UTF-8, the length of multi-byte characters is encoded in the MSB + if ((p[10] & 0x80) == 0) { + p += 11; + } else { + switch(p[10] & 0xf0) { + case 0xe0: + p += 13; + break; + case 0xf0: + p += 14; + break; + default: + p += 12; + break; + } + } + + len -= (p - dt_ptr); + rv = parse_isoformat_time(p, len, + &hour, &minute, &second, µsecond, + &tzoffset, &tzusec); + } + if (rv < 0) { + PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %s", dt_ptr); + return NULL; + } + + PyObject* tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, tzusec); + if (tzinfo == NULL) { + return NULL; + } + + PyObject* dt; + if ( (PyTypeObject*)cls == &PyDateTime_DateTimeType ) { + // Use the fast path constructor + dt = new_datetime(year, month, day, hour, minute, second, microsecond, + tzinfo, 0); + } else { + // Subclass + dt = PyObject_CallFunction(cls, "iiiiiiiO", + year, + month, + day, + hour, + minute, + second, + microsecond, + tzinfo); + } + + Py_DECREF(tzinfo); + return dt; +} + + /* * Destructor. */ @@ -5519,6 +5868,10 @@ static PyMethodDef datetime_methods[] = { METH_VARARGS | METH_KEYWORDS | METH_CLASS, PyDoc_STR("date, time -> datetime with same date and time fields")}, + {"fromisoformat", (PyCFunction)datetime_fromisoformat, + METH_O | METH_CLASS, + PyDoc_STR("string -> datetime from datetime.isoformat() output")}, + /* Instance methods: */ {"date", (PyCFunction)datetime_getdate, METH_NOARGS, From webhook-mailer at python.org Thu Dec 21 00:42:45 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 21 Dec 2017 05:42:45 -0000 Subject: [Python-checkins] correct the typos (GH-4950) (#4952) Message-ID: https://github.com/python/cpython/commit/e8ab7eb5c7a28cb6398d8fdaf24959af527a9ba4 commit: e8ab7eb5c7a28cb6398d8fdaf24959af527a9ba4 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-21T07:42:42+02:00 summary: correct the typos (GH-4950) (#4952) (cherry picked from commit 83cb778b4a3f856f2243b0f0d36fefb5c44b388f) files: M Modules/_cursesmodule.c diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 6f21dd8ba47..935712a0bed 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1049,7 +1049,7 @@ PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; default: - PyErr_SetString(PyExc_TypeError, "insch requires 1 or 4 arguments"); + PyErr_SetString(PyExc_TypeError, "insch requires 1 to 4 arguments"); return NULL; } @@ -1082,7 +1082,7 @@ PyCursesWindow_InCh(PyCursesWindowObject *self, PyObject *args) rtn = mvwinch(self->win,y,x); break; default: - PyErr_SetString(PyExc_TypeError, "inch requires 0 or 2 arguments"); + PyErr_SetString(PyExc_TypeError, "inch requires 0 to 2 arguments"); return NULL; } return PyInt_FromLong((long) rtn); From webhook-mailer at python.org Thu Dec 21 00:43:14 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 21 Dec 2017 05:43:14 -0000 Subject: [Python-checkins] correct the typos (GH-4950) (#4951) Message-ID: https://github.com/python/cpython/commit/020668b8e15c472e51110e20bb3df0672437db1e commit: 020668b8e15c472e51110e20bb3df0672437db1e branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-21T07:43:11+02:00 summary: correct the typos (GH-4950) (#4951) (cherry picked from commit 83cb778b4a3f856f2243b0f0d36fefb5c44b388f) files: M Modules/_cursesmodule.c diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 9a691dbe714..4ac702aa2f8 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1365,7 +1365,7 @@ PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; default: - PyErr_SetString(PyExc_TypeError, "insch requires 1 or 4 arguments"); + PyErr_SetString(PyExc_TypeError, "insch requires 1 to 4 arguments"); return NULL; } @@ -1396,7 +1396,7 @@ PyCursesWindow_InCh(PyCursesWindowObject *self, PyObject *args) rtn = mvwinch(self->win,y,x); break; default: - PyErr_SetString(PyExc_TypeError, "inch requires 0 or 2 arguments"); + PyErr_SetString(PyExc_TypeError, "inch requires 0 to 2 arguments"); return NULL; } return PyLong_FromUnsignedLong(rtn); From webhook-mailer at python.org Thu Dec 21 04:00:52 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 21 Dec 2017 09:00:52 -0000 Subject: [Python-checkins] Fix trivial typo in pickle.rst (#4955) Message-ID: https://github.com/python/cpython/commit/a8d25a16452f7ee8dfc350cd028b3ae172d28ada commit: a8d25a16452f7ee8dfc350cd028b3ae172d28ada branch: master author: Sebastian Pucilowski committer: Serhiy Storchaka date: 2017-12-21T11:00:49+02:00 summary: Fix trivial typo in pickle.rst (#4955) files: M Doc/library/pickle.rst diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index 6e8430fa8e6..d0c4cf937c8 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -370,7 +370,7 @@ The :mod:`pickle` module exports two classes, :class:`Pickler` and Python 2 names to the new names used in Python 3. The *encoding* and *errors* tell pickle how to decode 8-bit string instances pickled by Python 2; these default to 'ASCII' and 'strict', respectively. The *encoding* can - be 'bytes' to read these ?8-bit string instances as bytes objects. + be 'bytes' to read these 8-bit string instances as bytes objects. .. method:: load() From webhook-mailer at python.org Thu Dec 21 04:11:10 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 21 Dec 2017 09:11:10 -0000 Subject: [Python-checkins] Fix trivial typo in pickle.rst (GH-4955) (#4958) Message-ID: https://github.com/python/cpython/commit/45588c6dd1e8644abf7dde42f566a8f81c7cc4f0 commit: 45588c6dd1e8644abf7dde42f566a8f81c7cc4f0 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-21T11:11:06+02:00 summary: Fix trivial typo in pickle.rst (GH-4955) (#4958) (cherry picked from commit a8d25a16452f7ee8dfc350cd028b3ae172d28ada) files: M Doc/library/pickle.rst diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index 6e8430fa8e6..d0c4cf937c8 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -370,7 +370,7 @@ The :mod:`pickle` module exports two classes, :class:`Pickler` and Python 2 names to the new names used in Python 3. The *encoding* and *errors* tell pickle how to decode 8-bit string instances pickled by Python 2; these default to 'ASCII' and 'strict', respectively. The *encoding* can - be 'bytes' to read these ?8-bit string instances as bytes objects. + be 'bytes' to read these 8-bit string instances as bytes objects. .. method:: load() From solipsis at pitrou.net Thu Dec 21 04:13:35 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 21 Dec 2017 09:13:35 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=8 Message-ID: <20171221091335.26080.74E210497079E163@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [-7, 8, 0] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogOUcSlD', '--timeout', '7200'] From webhook-mailer at python.org Thu Dec 21 07:16:20 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 21 Dec 2017 12:16:20 -0000 Subject: [Python-checkins] bpo-32323: urllib.parse.urlsplit() must not lowercase() IPv6 scope value (#4867) Message-ID: https://github.com/python/cpython/commit/fbd605151fcf2899b14575f4ddb9ce3c55e684ab commit: fbd605151fcf2899b14575f4ddb9ce3c55e684ab branch: master author: ????????? ???? committer: Andrew Svetlov date: 2017-12-21T14:16:17+02:00 summary: bpo-32323: urllib.parse.urlsplit() must not lowercase() IPv6 scope value (#4867) files: A Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst M Lib/test/test_urlparse.py M Lib/urllib/parse.py diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index e5f6130e4a0..ddee1c38d8b 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -520,6 +520,15 @@ def _encode(t): self.assertEqual(result.url, defrag) self.assertEqual(result.fragment, frag) + def test_urlsplit_scoped_IPv6(self): + p = urllib.parse.urlsplit('http://[FE80::822a:a8ff:fe49:470c%tESt]:1234') + self.assertEqual(p.hostname, "fe80::822a:a8ff:fe49:470c%tESt") + self.assertEqual(p.netloc, '[FE80::822a:a8ff:fe49:470c%tESt]:1234') + + p = urllib.parse.urlsplit(b'http://[FE80::822a:a8ff:fe49:470c%tESt]:1234') + self.assertEqual(p.hostname, b"fe80::822a:a8ff:fe49:470c%tESt") + self.assertEqual(p.netloc, b'[FE80::822a:a8ff:fe49:470c%tESt]:1234') + def test_urlsplit_attributes(self): url = "HTTP://WWW.PYTHON.ORG/doc/#frag" p = urllib.parse.urlsplit(url) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 76086e58bea..58460f9234f 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -155,10 +155,12 @@ def password(self): def hostname(self): hostname = self._hostinfo[0] if not hostname: - hostname = None - elif hostname is not None: - hostname = hostname.lower() - return hostname + return None + # Scoped IPv6 address may have zone info, which must not be lowercased + # like http://[fe80::822a:a8ff:fe49:470c%tESt]:1234/keys + separator = '%' if isinstance(hostname, str) else b'%' + hostname, percent, zone = hostname.partition(separator) + return hostname.lower() + percent + zone @property def port(self): diff --git a/Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst b/Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst new file mode 100644 index 00000000000..3077d7cdfef --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst @@ -0,0 +1,2 @@ +:func:`urllib.parse.urlsplit()` does not convert zone-id (scope) to lower case +for scoped IPv6 addresses in hostnames now. From webhook-mailer at python.org Thu Dec 21 07:54:48 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 21 Dec 2017 12:54:48 -0000 Subject: [Python-checkins] bpo-32323: urllib.parse.urlsplit() must not lowercase() IPv6 scope value (GH-4867) (#4959) Message-ID: https://github.com/python/cpython/commit/fdb148f949e3ae66036b75163ff68042d19cf0fc commit: fdb148f949e3ae66036b75163ff68042d19cf0fc branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-21T14:54:45+02:00 summary: bpo-32323: urllib.parse.urlsplit() must not lowercase() IPv6 scope value (GH-4867) (#4959) (cherry picked from commit fbd605151fcf2899b14575f4ddb9ce3c55e684ab) files: A Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst M Lib/test/test_urlparse.py M Lib/urllib/parse.py diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index e5f6130e4a0..ddee1c38d8b 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -520,6 +520,15 @@ def _encode(t): self.assertEqual(result.url, defrag) self.assertEqual(result.fragment, frag) + def test_urlsplit_scoped_IPv6(self): + p = urllib.parse.urlsplit('http://[FE80::822a:a8ff:fe49:470c%tESt]:1234') + self.assertEqual(p.hostname, "fe80::822a:a8ff:fe49:470c%tESt") + self.assertEqual(p.netloc, '[FE80::822a:a8ff:fe49:470c%tESt]:1234') + + p = urllib.parse.urlsplit(b'http://[FE80::822a:a8ff:fe49:470c%tESt]:1234') + self.assertEqual(p.hostname, b"fe80::822a:a8ff:fe49:470c%tESt") + self.assertEqual(p.netloc, b'[FE80::822a:a8ff:fe49:470c%tESt]:1234') + def test_urlsplit_attributes(self): url = "HTTP://WWW.PYTHON.ORG/doc/#frag" p = urllib.parse.urlsplit(url) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 3cab2d13d5f..f959212b8bb 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -155,10 +155,12 @@ def password(self): def hostname(self): hostname = self._hostinfo[0] if not hostname: - hostname = None - elif hostname is not None: - hostname = hostname.lower() - return hostname + return None + # Scoped IPv6 address may have zone info, which must not be lowercased + # like http://[fe80::822a:a8ff:fe49:470c%tESt]:1234/keys + separator = '%' if isinstance(hostname, str) else b'%' + hostname, percent, zone = hostname.partition(separator) + return hostname.lower() + percent + zone @property def port(self): diff --git a/Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst b/Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst new file mode 100644 index 00000000000..3077d7cdfef --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-14-10-10-10.bpo-32323.ideco.rst @@ -0,0 +1,2 @@ +:func:`urllib.parse.urlsplit()` does not convert zone-id (scope) to lower case +for scoped IPv6 addresses in hostnames now. From webhook-mailer at python.org Thu Dec 21 09:45:22 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 21 Dec 2017 14:45:22 -0000 Subject: [Python-checkins] bpo-32030: Add _Py_EncodeUTF8_surrogateescape() (#4960) Message-ID: https://github.com/python/cpython/commit/e47e698da6bd982da277960c14afa9d9939e3155 commit: e47e698da6bd982da277960c14afa9d9939e3155 branch: master author: Victor Stinner committer: GitHub date: 2017-12-21T15:45:16+01:00 summary: bpo-32030: Add _Py_EncodeUTF8_surrogateescape() (#4960) Py_EncodeLocale() now uses _Py_EncodeUTF8_surrogateescape(), instead of using temporary unicode and bytes objects. So Py_EncodeLocale() doesn't use the Python C API anymore. files: M Objects/unicodeobject.c M Python/fileutils.c diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index c8600a89413..716e352dea6 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5147,6 +5147,95 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size, size_t *p_wlen) } +/* UTF-8 encoder using the surrogateescape error handler . + + On success, return a pointer to a newly allocated character string (use + PyMem_Free() to free the memory). + + On encoding failure, return NULL and write the position of the invalid + surrogate character into *error_pos (if error_pos is set). + + On memory allocation failure, return NULL and write (size_t)-1 into + *error_pos (if error_pos is set). */ +char* +_Py_EncodeUTF8_surrogateescape(const wchar_t *text, size_t *error_pos) +{ + const Py_ssize_t max_char_size = 4; + Py_ssize_t len = wcslen(text); + + assert(len >= 0); + + char *bytes; + if (len <= PY_SSIZE_T_MAX / max_char_size - 1) { + bytes = PyMem_Malloc((len + 1) * max_char_size); + } + else { + bytes = NULL; + } + if (bytes == NULL) { + if (error_pos != NULL) { + *error_pos = (size_t)-1; + } + return NULL; + } + + char *p = bytes; + Py_ssize_t i; + for (i = 0; i < len;) { + Py_UCS4 ch = text[i++]; + + if (ch < 0x80) { + /* Encode ASCII */ + *p++ = (char) ch; + + } + else if (ch < 0x0800) { + /* Encode Latin-1 */ + *p++ = (char)(0xc0 | (ch >> 6)); + *p++ = (char)(0x80 | (ch & 0x3f)); + } + else if (Py_UNICODE_IS_SURROGATE(ch)) { + /* surrogateescape error handler */ + if (!(0xDC80 <= ch && ch <= 0xDCFF)) { + if (error_pos != NULL) { + *error_pos = (size_t)i - 1; + } + goto error; + } + *p++ = (char)(ch & 0xff); + } + else if (ch < 0x10000) { + *p++ = (char)(0xe0 | (ch >> 12)); + *p++ = (char)(0x80 | ((ch >> 6) & 0x3f)); + *p++ = (char)(0x80 | (ch & 0x3f)); + } + else { /* ch >= 0x10000 */ + assert(ch <= MAX_UNICODE); + /* Encode UCS4 Unicode ordinals */ + *p++ = (char)(0xf0 | (ch >> 18)); + *p++ = (char)(0x80 | ((ch >> 12) & 0x3f)); + *p++ = (char)(0x80 | ((ch >> 6) & 0x3f)); + *p++ = (char)(0x80 | (ch & 0x3f)); + } + } + *p++ = '\0'; + + size_t final_size = (p - bytes); + char *bytes2 = PyMem_Realloc(bytes, final_size); + if (bytes2 == NULL) { + if (error_pos != NULL) { + *error_pos = (size_t)-1; + } + goto error; + } + return bytes2; + + error: + PyMem_Free(bytes); + return NULL; +} + + /* Primary internal function which creates utf8 encoded bytes objects. Allocation strategy: if the string is short, convert into a stack buffer diff --git a/Python/fileutils.c b/Python/fileutils.c index c4d495d0d63..eeb5f2e89d2 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -22,6 +22,8 @@ extern int winerror_to_errno(int); extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size, size_t *p_wlen); +extern char* _Py_EncodeUTF8_surrogateescape(const wchar_t *text, + size_t *error_pos); #ifdef O_CLOEXEC /* Does open() support the O_CLOEXEC flag? Possible values: @@ -418,42 +420,6 @@ Py_DecodeLocale(const char* arg, size_t *size) #endif /* __APPLE__ or __ANDROID__ */ } -static char* -_Py_EncodeLocaleUTF8(const wchar_t *text, size_t *error_pos) -{ - Py_ssize_t len; - PyObject *unicode, *bytes = NULL; - char *cpath; - - unicode = PyUnicode_FromWideChar(text, wcslen(text)); - if (unicode == NULL) { - return NULL; - } - - bytes = _PyUnicode_AsUTF8String(unicode, "surrogateescape"); - Py_DECREF(unicode); - if (bytes == NULL) { - PyErr_Clear(); - if (error_pos != NULL) { - *error_pos = (size_t)-1; - } - return NULL; - } - - len = PyBytes_GET_SIZE(bytes); - cpath = PyMem_Malloc(len+1); - if (cpath == NULL) { - PyErr_Clear(); - Py_DECREF(bytes); - if (error_pos != NULL) { - *error_pos = (size_t)-1; - } - return NULL; - } - memcpy(cpath, PyBytes_AsString(bytes), len + 1); - Py_DECREF(bytes); - return cpath; -} #if !defined(__APPLE__) && !defined(__ANDROID__) static char* @@ -537,10 +503,10 @@ char* Py_EncodeLocale(const wchar_t *text, size_t *error_pos) { #if defined(__APPLE__) || defined(__ANDROID__) - return _Py_EncodeLocaleUTF8(text, error_pos); + return _Py_EncodeUTF8_surrogateescape(text, error_pos); #else /* __APPLE__ */ if (Py_UTF8Mode == 1) { - return _Py_EncodeLocaleUTF8(text, error_pos); + return _Py_EncodeUTF8_surrogateescape(text, error_pos); } #ifndef MS_WINDOWS From webhook-mailer at python.org Thu Dec 21 10:06:49 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 21 Dec 2017 15:06:49 -0000 Subject: [Python-checkins] bpo-26133: Dont unsubscribe signals in UNIX even loop on interpreter shutdown (#4956) Message-ID: https://github.com/python/cpython/commit/4a02543cf97e8cbf9293741379f977b85531e4c2 commit: 4a02543cf97e8cbf9293741379f977b85531e4c2 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-21T17:06:46+02:00 summary: bpo-26133: Dont unsubscribe signals in UNIX even loop on interpreter shutdown (#4956) files: A Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst M Lib/asyncio/unix_events.py diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 69c719c3239..ec767f57d3a 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -51,8 +51,14 @@ def __init__(self, selector=None): def close(self): super().close() - for sig in list(self._signal_handlers): - self.remove_signal_handler(sig) + if not sys.is_finalizing(): + for sig in list(self._signal_handlers): + self.remove_signal_handler(sig) + else: + warinigs.warn(f"Closing the loop {self!r} on interpreter shutdown " + f"stage, signal unsubsription is disabled", + ResourceWarning, + source=self) def _process_self_data(self, data): for signum in data: diff --git a/Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst b/Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst new file mode 100644 index 00000000000..0653d1960e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst @@ -0,0 +1 @@ +Don't unsubscribe signals in asyncio UNIX event loop on interpreter shutdown. From webhook-mailer at python.org Thu Dec 21 10:20:35 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 21 Dec 2017 15:20:35 -0000 Subject: [Python-checkins] bpo-32030: Add _Py_EncodeLocaleRaw() (#4961) Message-ID: https://github.com/python/cpython/commit/9dd762013fd9fcf975ad51700b55d050ca9ed60e commit: 9dd762013fd9fcf975ad51700b55d050ca9ed60e branch: master author: Victor Stinner committer: GitHub date: 2017-12-21T16:20:32+01:00 summary: bpo-32030: Add _Py_EncodeLocaleRaw() (#4961) Replace Py_EncodeLocale() with _Py_EncodeLocaleRaw() in: * _Py_wfopen() * _Py_wreadlink() * _Py_wrealpath() * _Py_wstat() * pymain_open_filename() These functions are called early during Python intialization, only the RAW memory allocator must be used. files: M Include/fileutils.h M Modules/getpath.c M Modules/main.c M Objects/unicodeobject.c M Python/fileutils.c diff --git a/Include/fileutils.h b/Include/fileutils.h index 900c70faad7..b7b6cd26c00 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -13,10 +13,13 @@ PyAPI_FUNC(wchar_t *) Py_DecodeLocale( PyAPI_FUNC(char*) Py_EncodeLocale( const wchar_t *text, size_t *error_pos); + +PyAPI_FUNC(char*) _Py_EncodeLocaleRaw( + const wchar_t *text, + size_t *error_pos); #endif #ifndef Py_LIMITED_API - PyAPI_FUNC(PyObject *) _Py_device_encoding(int); #ifdef MS_WINDOWS diff --git a/Modules/getpath.c b/Modules/getpath.c index b4b33437b6f..494fa19bdf3 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -140,13 +140,13 @@ _Py_wstat(const wchar_t* path, struct stat *buf) { int err; char *fname; - fname = Py_EncodeLocale(path, NULL); + fname = _Py_EncodeLocaleRaw(path, NULL); if (fname == NULL) { errno = EINVAL; return -1; } err = stat(fname, buf); - PyMem_Free(fname); + PyMem_RawFree(fname); return err; } diff --git a/Modules/main.c b/Modules/main.c index 1bf706b162c..dff7894bf35 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1490,14 +1490,14 @@ pymain_open_filename(_PyMain *pymain) char *cfilename_buffer; const char *cfilename; int err = errno; - cfilename_buffer = Py_EncodeLocale(pymain->filename, NULL); + cfilename_buffer = _Py_EncodeLocaleRaw(pymain->filename, NULL); if (cfilename_buffer != NULL) cfilename = cfilename_buffer; else cfilename = ""; fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n", pymain->config.program, cfilename, err, strerror(err)); - PyMem_Free(cfilename_buffer); + PyMem_RawFree(cfilename_buffer); pymain->status = 2; return NULL; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 716e352dea6..92a6ad6b979 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5158,7 +5158,8 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size, size_t *p_wlen) On memory allocation failure, return NULL and write (size_t)-1 into *error_pos (if error_pos is set). */ char* -_Py_EncodeUTF8_surrogateescape(const wchar_t *text, size_t *error_pos) +_Py_EncodeUTF8_surrogateescape(const wchar_t *text, size_t *error_pos, + int raw_malloc) { const Py_ssize_t max_char_size = 4; Py_ssize_t len = wcslen(text); @@ -5167,7 +5168,12 @@ _Py_EncodeUTF8_surrogateescape(const wchar_t *text, size_t *error_pos) char *bytes; if (len <= PY_SSIZE_T_MAX / max_char_size - 1) { - bytes = PyMem_Malloc((len + 1) * max_char_size); + if (raw_malloc) { + bytes = PyMem_RawMalloc((len + 1) * max_char_size); + } + else { + bytes = PyMem_Malloc((len + 1) * max_char_size); + } } else { bytes = NULL; @@ -5221,7 +5227,13 @@ _Py_EncodeUTF8_surrogateescape(const wchar_t *text, size_t *error_pos) *p++ = '\0'; size_t final_size = (p - bytes); - char *bytes2 = PyMem_Realloc(bytes, final_size); + char *bytes2; + if (raw_malloc) { + bytes2 = PyMem_RawRealloc(bytes, final_size); + } + else { + bytes2 = PyMem_Realloc(bytes, final_size); + } if (bytes2 == NULL) { if (error_pos != NULL) { *error_pos = (size_t)-1; @@ -5231,7 +5243,12 @@ _Py_EncodeUTF8_surrogateescape(const wchar_t *text, size_t *error_pos) return bytes2; error: - PyMem_Free(bytes); + if (raw_malloc) { + PyMem_RawFree(bytes); + } + else { + PyMem_Free(bytes); + } return NULL; } diff --git a/Python/fileutils.c b/Python/fileutils.c index eeb5f2e89d2..1ccd4baa6d2 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -23,7 +23,7 @@ extern int winerror_to_errno(int); extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size, size_t *p_wlen); extern char* _Py_EncodeUTF8_surrogateescape(const wchar_t *text, - size_t *error_pos); + size_t *error_pos, int raw_malloc); #ifdef O_CLOEXEC /* Does open() support the O_CLOEXEC flag? Possible values: @@ -183,7 +183,7 @@ check_force_ascii(void) } static char* -encode_ascii_surrogateescape(const wchar_t *text, size_t *error_pos) +encode_ascii_surrogateescape(const wchar_t *text, size_t *error_pos, int raw_malloc) { char *result = NULL, *out; size_t len, i; @@ -194,7 +194,13 @@ encode_ascii_surrogateescape(const wchar_t *text, size_t *error_pos) len = wcslen(text); - result = PyMem_Malloc(len + 1); /* +1 for NUL byte */ + /* +1 for NUL byte */ + if (raw_malloc) { + result = PyMem_RawMalloc(len + 1); + } + else { + result = PyMem_Malloc(len + 1); + } if (result == NULL) return NULL; @@ -211,9 +217,15 @@ encode_ascii_surrogateescape(const wchar_t *text, size_t *error_pos) *out++ = (char)(ch - 0xdc00); } else { - if (error_pos != NULL) + if (error_pos != NULL) { *error_pos = i; - PyMem_Free(result); + } + if (raw_malloc) { + PyMem_RawFree(result); + } + else { + PyMem_Free(result); + } return NULL; } } @@ -423,7 +435,7 @@ Py_DecodeLocale(const char* arg, size_t *size) #if !defined(__APPLE__) && !defined(__ANDROID__) static char* -encode_locale(const wchar_t *text, size_t *error_pos) +encode_current_locale(const wchar_t *text, size_t *error_pos, int raw_malloc) { const size_t len = wcslen(text); char *result = NULL, *bytes = NULL; @@ -455,8 +467,14 @@ encode_locale(const wchar_t *text, size_t *error_pos) else converted = wcstombs(NULL, buf, 0); if (converted == (size_t)-1) { - if (result != NULL) - PyMem_Free(result); + if (result != NULL) { + if (raw_malloc) { + PyMem_RawFree(result); + } + else { + PyMem_Free(result); + } + } if (error_pos != NULL) *error_pos = i; return NULL; @@ -475,10 +493,16 @@ encode_locale(const wchar_t *text, size_t *error_pos) } size += 1; /* nul byte at the end */ - result = PyMem_Malloc(size); + if (raw_malloc) { + result = PyMem_RawMalloc(size); + } + else { + result = PyMem_Malloc(size); + } if (result == NULL) { - if (error_pos != NULL) + if (error_pos != NULL) { *error_pos = (size_t)-1; + } return NULL; } bytes = result; @@ -487,6 +511,28 @@ encode_locale(const wchar_t *text, size_t *error_pos) } #endif +static char* +encode_locale(const wchar_t *text, size_t *error_pos, int raw_malloc) +{ +#if defined(__APPLE__) || defined(__ANDROID__) + return _Py_EncodeUTF8_surrogateescape(text, error_pos, raw_malloc); +#else /* __APPLE__ */ + if (Py_UTF8Mode == 1) { + return _Py_EncodeUTF8_surrogateescape(text, error_pos, raw_malloc); + } + +#ifndef MS_WINDOWS + if (force_ascii == -1) + force_ascii = check_force_ascii(); + + if (force_ascii) + return encode_ascii_surrogateescape(text, error_pos, raw_malloc); +#endif + + return encode_current_locale(text, error_pos, raw_malloc); +#endif /* __APPLE__ or __ANDROID__ */ +} + /* Encode a wide character string to the locale encoding with the surrogateescape error handler: surrogate characters in the range U+DC80..U+DCFF are converted to bytes 0x80..0xFF. @@ -502,23 +548,16 @@ encode_locale(const wchar_t *text, size_t *error_pos) char* Py_EncodeLocale(const wchar_t *text, size_t *error_pos) { -#if defined(__APPLE__) || defined(__ANDROID__) - return _Py_EncodeUTF8_surrogateescape(text, error_pos); -#else /* __APPLE__ */ - if (Py_UTF8Mode == 1) { - return _Py_EncodeUTF8_surrogateescape(text, error_pos); - } - -#ifndef MS_WINDOWS - if (force_ascii == -1) - force_ascii = check_force_ascii(); + return encode_locale(text, error_pos, 0); +} - if (force_ascii) - return encode_ascii_surrogateescape(text, error_pos); -#endif - return encode_locale(text, error_pos); -#endif /* __APPLE__ or __ANDROID__ */ +/* Similar to Py_EncodeLocale(), but result must be freed by PyMem_RawFree() + instead of PyMem_Free(). */ +char* +_Py_EncodeLocaleRaw(const wchar_t *text, size_t *error_pos) +{ + return encode_locale(text, error_pos, 1); } @@ -1029,11 +1068,12 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode) errno = EINVAL; return NULL; } - cpath = Py_EncodeLocale(path, NULL); - if (cpath == NULL) + cpath = _Py_EncodeLocaleRaw(path, NULL); + if (cpath == NULL) { return NULL; + } f = fopen(cpath, cmode); - PyMem_Free(cpath); + PyMem_RawFree(cpath); #else f = _wfopen(path, mode); #endif @@ -1341,13 +1381,13 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) int res; size_t r1; - cpath = Py_EncodeLocale(path, NULL); + cpath = _Py_EncodeLocaleRaw(path, NULL); if (cpath == NULL) { errno = EINVAL; return -1; } res = (int)readlink(cpath, cbuf, Py_ARRAY_LENGTH(cbuf)); - PyMem_Free(cpath); + PyMem_RawFree(cpath); if (res == -1) return -1; if (res == Py_ARRAY_LENGTH(cbuf)) { @@ -1386,13 +1426,13 @@ _Py_wrealpath(const wchar_t *path, wchar_t *wresolved_path; char *res; size_t r; - cpath = Py_EncodeLocale(path, NULL); + cpath = _Py_EncodeLocaleRaw(path, NULL); if (cpath == NULL) { errno = EINVAL; return NULL; } res = realpath(cpath, cresolved_path); - PyMem_Free(cpath); + PyMem_RawFree(cpath); if (res == NULL) return NULL; From webhook-mailer at python.org Thu Dec 21 10:49:20 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 21 Dec 2017 15:49:20 -0000 Subject: [Python-checkins] bpo-32030: Add _Py_FindEnvConfigValue() (#4963) Message-ID: https://github.com/python/cpython/commit/9bee329130aae5a13050c08dab9d349b76e66835 commit: 9bee329130aae5a13050c08dab9d349b76e66835 branch: master author: Victor Stinner committer: GitHub date: 2017-12-21T16:49:13+01:00 summary: bpo-32030: Add _Py_FindEnvConfigValue() (#4963) Add a new _Py_FindEnvConfigValue() function: code shared between Windows and Unix implementations of _PyPathConfig_Calculate() to read the pyenv.cfg file. _Py_FindEnvConfigValue() now uses _Py_DecodeUTF8_surrogateescape() instead of using a Python Unicode string, the Python API must not be used early during Python initialization. Same change in Unix search_for_exec_prefix(): use _Py_DecodeUTF8_surrogateescape(). Cleanup also encode_current_locale(): PyMem_RawFree/PyMem_Free can be called with NULL. Fix also "NUL byte" => "NULL byte" typo. files: M Include/fileutils.h M Include/pylifecycle.h M Modules/getpath.c M PC/getpathp.c M Python/fileutils.c M Python/pathconfig.c diff --git a/Include/fileutils.h b/Include/fileutils.h index b7b6cd26c00..d027e18348f 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -19,6 +19,13 @@ PyAPI_FUNC(char*) _Py_EncodeLocaleRaw( size_t *error_pos); #endif +#ifdef Py_BUILD_CORE +PyAPI_FUNC(wchar_t*) _Py_DecodeUTF8_surrogateescape( + const char *s, + Py_ssize_t size, + size_t *p_wlen); +#endif + #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _Py_device_encoding(int); diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index da740fef23a..659c6df644e 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -118,6 +118,11 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(const _PyCoreConfig *core_config); PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv); +PyAPI_FUNC(int) _Py_FindEnvConfigValue( + FILE *env_file, + const wchar_t *key, + wchar_t *value, + size_t value_size); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS diff --git a/Modules/getpath.c b/Modules/getpath.c index 494fa19bdf3..85e737b61d0 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -296,62 +296,6 @@ absolutize(wchar_t *path) } -/* search for a prefix value in an environment file. If found, copy it - to the provided buffer, which is expected to be no more than MAXPATHLEN - bytes long. -*/ -static int -find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) -{ - int result = 0; /* meaning not found */ - char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */ - - fseek(env_file, 0, SEEK_SET); - while (!feof(env_file)) { - char * p = fgets(buffer, MAXPATHLEN*2, env_file); - wchar_t tmpbuffer[MAXPATHLEN*2+1]; - PyObject * decoded; - int n; - - if (p == NULL) { - break; - } - n = strlen(p); - if (p[n - 1] != '\n') { - /* line has overflowed - bail */ - break; - } - if (p[0] == '#') { - /* Comment - skip */ - continue; - } - decoded = PyUnicode_DecodeUTF8(buffer, n, "surrogateescape"); - if (decoded != NULL) { - Py_ssize_t k; - wchar_t * state; - k = PyUnicode_AsWideChar(decoded, - tmpbuffer, MAXPATHLEN * 2); - Py_DECREF(decoded); - if (k >= 0) { - wchar_t * tok = wcstok(tmpbuffer, L" \t\r\n", &state); - if ((tok != NULL) && !wcscmp(tok, key)) { - tok = wcstok(NULL, L" \t", &state); - if ((tok != NULL) && !wcscmp(tok, L"=")) { - tok = wcstok(NULL, L"\r\n", &state); - if (tok != NULL) { - wcsncpy(value, tok, MAXPATHLEN); - result = 1; - break; - } - } - } - } - } - } - return result; -} - - /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN bytes long. */ @@ -501,24 +445,17 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, } else { char buf[MAXPATHLEN+1]; - PyObject *decoded; - wchar_t rel_builddir_path[MAXPATHLEN+1]; + wchar_t *rel_builddir_path; n = fread(buf, 1, MAXPATHLEN, f); buf[n] = '\0'; fclose(f); - decoded = PyUnicode_DecodeUTF8(buf, n, "surrogateescape"); - if (decoded != NULL) { - Py_ssize_t k; - k = PyUnicode_AsWideChar(decoded, - rel_builddir_path, MAXPATHLEN); - Py_DECREF(decoded); - if (k >= 0) { - rel_builddir_path[k] = L'\0'; - wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); - exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(exec_prefix, rel_builddir_path); - return -1; - } + rel_builddir_path = _Py_DecodeUTF8_surrogateescape(buf, n, NULL); + if (rel_builddir_path != NULL) { + wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; + joinpath(exec_prefix, rel_builddir_path); + PyMem_RawFree(rel_builddir_path ); + return -1; } } } @@ -784,7 +721,7 @@ calculate_read_pyenv(PyCalculatePath *calculate) } /* Look for a 'home' variable and set argv0_path to it, if found */ - if (find_env_config_value(env_file, L"home", tmpbuffer)) { + if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, MAXPATHLEN)) { wcscpy(calculate->argv0_path, tmpbuffer); } fclose(env_file); diff --git a/PC/getpathp.c b/PC/getpathp.c index fe4ef1a1ab3..c4977e79979 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -564,58 +564,6 @@ get_program_full_path(const _PyCoreConfig *core_config, } -static int -find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) -{ - int result = 0; /* meaning not found */ - char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */ - - fseek(env_file, 0, SEEK_SET); - while (!feof(env_file)) { - char * p = fgets(buffer, MAXPATHLEN*2, env_file); - wchar_t tmpbuffer[MAXPATHLEN*2+1]; - PyObject * decoded; - size_t n; - - if (p == NULL) { - break; - } - n = strlen(p); - if (p[n - 1] != '\n') { - /* line has overflowed - bail */ - break; - } - if (p[0] == '#') { - /* Comment - skip */ - continue; - } - decoded = PyUnicode_DecodeUTF8(buffer, n, "surrogateescape"); - if (decoded != NULL) { - Py_ssize_t k; - k = PyUnicode_AsWideChar(decoded, - tmpbuffer, MAXPATHLEN * 2); - Py_DECREF(decoded); - if (k >= 0) { - wchar_t * context = NULL; - wchar_t * tok = wcstok_s(tmpbuffer, L" \t\r\n", &context); - if ((tok != NULL) && !wcscmp(tok, key)) { - tok = wcstok_s(NULL, L" \t", &context); - if ((tok != NULL) && !wcscmp(tok, L"=")) { - tok = wcstok_s(NULL, L"\r\n", &context); - if (tok != NULL) { - wcsncpy(value, tok, MAXPATHLEN); - result = 1; - break; - } - } - } - } - } - } - return result; -} - - static int read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path, int *isolated, int *nosite) @@ -765,9 +713,11 @@ calculate_pyvenv_file(PyCalculatePath *calculate) FILE *env_file = _Py_wfopen(envbuffer, L"r"); if (env_file == NULL) { errno = 0; + reduce(envbuffer); reduce(envbuffer); join(envbuffer, env_cfg); + env_file = _Py_wfopen(envbuffer, L"r"); if (env_file == NULL) { errno = 0; @@ -780,7 +730,7 @@ calculate_pyvenv_file(PyCalculatePath *calculate) /* Look for a 'home' variable and set argv0_path to it, if found */ wchar_t tmpbuffer[MAXPATHLEN+1]; - if (find_env_config_value(env_file, L"home", tmpbuffer)) { + if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, MAXPATHLEN)) { wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, tmpbuffer); } fclose(env_file); diff --git a/Python/fileutils.c b/Python/fileutils.c index 1ccd4baa6d2..645a1793664 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -20,8 +20,6 @@ extern int winerror_to_errno(int); #include #endif /* HAVE_FCNTL_H */ -extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size, - size_t *p_wlen); extern char* _Py_EncodeUTF8_surrogateescape(const wchar_t *text, size_t *error_pos, int raw_malloc); @@ -194,7 +192,7 @@ encode_ascii_surrogateescape(const wchar_t *text, size_t *error_pos, int raw_mal len = wcslen(text); - /* +1 for NUL byte */ + /* +1 for NULL byte */ if (raw_malloc) { result = PyMem_RawMalloc(len + 1); } @@ -467,13 +465,11 @@ encode_current_locale(const wchar_t *text, size_t *error_pos, int raw_malloc) else converted = wcstombs(NULL, buf, 0); if (converted == (size_t)-1) { - if (result != NULL) { - if (raw_malloc) { - PyMem_RawFree(result); - } - else { - PyMem_Free(result); - } + if (raw_malloc) { + PyMem_RawFree(result); + } + else { + PyMem_Free(result); } if (error_pos != NULL) *error_pos = i; diff --git a/Python/pathconfig.c b/Python/pathconfig.c index acb25b6fa89..9591fcc4911 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -354,6 +354,56 @@ _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv) return PyUnicode_FromWideChar(argv0, n); } + +/* Search for a prefix value in an environment file (pyvenv.cfg). + If found, copy it into the provided buffer. */ +int +_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key, + wchar_t *value, size_t value_size) +{ + int result = 0; /* meaning not found */ + char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */ + + fseek(env_file, 0, SEEK_SET); + while (!feof(env_file)) { + char * p = fgets(buffer, MAXPATHLEN*2, env_file); + wchar_t *tmpbuffer; + int n; + + if (p == NULL) { + break; + } + n = strlen(p); + if (p[n - 1] != '\n') { + /* line has overflowed - bail */ + break; + } + if (p[0] == '#') { + /* Comment - skip */ + continue; + } + tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL); + if (tmpbuffer != NULL) { + wchar_t * state; + wchar_t * tok = wcstok(tmpbuffer, L" \t\r\n", &state); + if ((tok != NULL) && !wcscmp(tok, key)) { + tok = wcstok(NULL, L" \t", &state); + if ((tok != NULL) && !wcscmp(tok, L"=")) { + tok = wcstok(NULL, L"\r\n", &state); + if (tok != NULL) { + wcsncpy(value, tok, MAXPATHLEN); + result = 1; + PyMem_RawFree(tmpbuffer); + break; + } + } + } + PyMem_RawFree(tmpbuffer); + } + } + return result; +} + #ifdef __cplusplus } #endif From webhook-mailer at python.org Thu Dec 21 12:42:34 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 21 Dec 2017 17:42:34 -0000 Subject: [Python-checkins] bpo-26133: Dont unsubscribe signals in UNIX even loop on interpreter shutdown (GH-4956) (#4962) Message-ID: https://github.com/python/cpython/commit/3bc68cff5b821e83ee5df8b8cd13f4f54151b406 commit: 3bc68cff5b821e83ee5df8b8cd13f4f54151b406 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-21T19:42:32+02:00 summary: bpo-26133: Dont unsubscribe signals in UNIX even loop on interpreter shutdown (GH-4956) (#4962) (cherry picked from commit 4a02543cf97e8cbf9293741379f977b85531e4c2) files: A Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst M Lib/asyncio/unix_events.py diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 5ea6c20c674..dde1d3588f2 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -61,8 +61,14 @@ def _socketpair(self): def close(self): super().close() - for sig in list(self._signal_handlers): - self.remove_signal_handler(sig) + if not sys.is_finalizing(): + for sig in list(self._signal_handlers): + self.remove_signal_handler(sig) + else: + warinigs.warn(f"Closing the loop {self!r} on interpreter shutdown " + f"stage, signal unsubsription is disabled", + ResourceWarning, + source=self) def _process_self_data(self, data): for signum in data: diff --git a/Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst b/Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst new file mode 100644 index 00000000000..0653d1960e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-21-11-08-42.bpo-26133.mt81QV.rst @@ -0,0 +1 @@ +Don't unsubscribe signals in asyncio UNIX event loop on interpreter shutdown. From webhook-mailer at python.org Thu Dec 21 18:05:07 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 21 Dec 2017 23:05:07 -0000 Subject: [Python-checkins] bpo-20891: Skip test_embed.test_bpo20891() (#4967) Message-ID: https://github.com/python/cpython/commit/550ee051d605b909dd75ef686d8e1244a0994394 commit: 550ee051d605b909dd75ef686d8e1244a0994394 branch: master author: Victor Stinner committer: GitHub date: 2017-12-22T00:05:05+01:00 summary: bpo-20891: Skip test_embed.test_bpo20891() (#4967) Skip the test failing randomly because of known race condition. Skip the test to fix macOS buildbots until a decision is made on the proper fix for the race condition. files: M Lib/test/test_embed.py diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index c7f45b59acc..c9b65485ac7 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -198,6 +198,9 @@ def test_pre_initialization_api(self): self.assertEqual(out, '') self.assertEqual(err, '') + @unittest.skipIf(True, + "FIXME: test fails randomly because of a race conditon, " + "see bpo-20891") def test_bpo20891(self): """ bpo-20891: Calling PyGILState_Ensure in a non-Python thread before From webhook-mailer at python.org Thu Dec 21 18:09:29 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 21 Dec 2017 23:09:29 -0000 Subject: [Python-checkins] bpo-29240: Skip test_readline.test_nonascii() (#4968) Message-ID: https://github.com/python/cpython/commit/424315fa865b43f67e36a40647107379adf031da commit: 424315fa865b43f67e36a40647107379adf031da branch: master author: Victor Stinner committer: GitHub date: 2017-12-22T00:09:26+01:00 summary: bpo-29240: Skip test_readline.test_nonascii() (#4968) Skip the test which fails on FreeBSD with POSIX locale. Skip the test to fix FreeBSD buildbots, until a fix can be found, so the buildbots can catch other regressions. files: M Lib/test/test_readline.py diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py index b4c25dee9d3..28ea38b747e 100644 --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -152,6 +152,8 @@ def test_auto_history_disabled(self): output = run_pty(self.auto_history_script.format(False)) self.assertIn(b"History length: 0\r\n", output) + @unittest.skipIf(True, + "FIXME: test broken by bpo-29240") def test_nonascii(self): try: readline.add_history("\xEB\xEF") From webhook-mailer at python.org Thu Dec 21 18:32:30 2017 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 21 Dec 2017 23:32:30 -0000 Subject: [Python-checkins] bpo-20891: Skip test_embed.test_bpo20891() (#4967) (#4969) Message-ID: https://github.com/python/cpython/commit/2e1ef00171179a8b906631b175cde2e68a804522 commit: 2e1ef00171179a8b906631b175cde2e68a804522 branch: 3.6 author: Victor Stinner committer: GitHub date: 2017-12-22T00:32:27+01:00 summary: bpo-20891: Skip test_embed.test_bpo20891() (#4967) (#4969) Skip the test failing randomly because of known race condition. Skip the test to fix macOS buildbots until a decision is made on the proper fix for the race condition. (cherry picked from commit 550ee051d605b909dd75ef686d8e1244a0994394) files: M Lib/test/test_capi.py diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 6e4286ed881..848a5289bab 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -494,6 +494,9 @@ def test_pre_initialization_api(self): self.assertEqual(out, '') self.assertEqual(err, '') + @unittest.skipIf(True, + "FIXME: test fails randomly because of a race conditon, " + "see bpo-20891") def test_bpo20891(self): """ bpo-20891: Calling PyGILState_Ensure in a non-Python thread before From lp_benchmark_robot at intel.com Thu Dec 21 21:53:07 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 21 Dec 2017 18:53:07 -0800 Subject: [Python-checkins] [1 down, 2 up, 62 flat] Results for Python (master branch) 2017-12-21 Message-ID: Results for project python/master, build date: 2017-12-21 03:03:40-08:00. - commit: a8d25a1 - previous commit: 776407f - revision date: 2017-12-21 11:00:49+02:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.881% | +0.436% | +5.476% | +8.291% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.935% | -1.835% | +22.977% | +10.347% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.731% | -0.277% | +25.303% | +7.795% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.103% | -1.476% | +22.215% | +8.818% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.986% | -0.137% | +8.169% | +11.724% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.237% | -0.099% | +10.473% | +12.875% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.562% | +0.064% | +6.145% | +12.325% | +-----+------------------------+--------+------------+------------+------------+ | :-) | crypto_pyaes| 0.504% | +2.338% | -0.807% | +8.511% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 2.787% | +1.103% | +11.004% | +17.530% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.488% | -0.372% | +12.318% | +15.052% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.230% | +0.218% | +3.778% | +7.011% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.828% | +0.534% | +4.750% | +5.731% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.752% | +0.504% | +2.244% | +7.408% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.108% | +0.043% | +12.813% | +11.073% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 2.148% | -0.162% | +8.229% | +11.559% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.971% | +0.638% | +6.792% | +11.279% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.451% | -0.418% | +9.952% | +12.993% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.980% | +1.751% | +7.408% | +11.274% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.310% | +1.865% | +3.372% | +9.637% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 0.932% | -5.727% | -4.976% | +16.558% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.681% | -0.644% | +7.293% | +13.838% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.384% | -0.138% | +46.955% | +12.317% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.335% | -1.116% | +7.339% | +16.095% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.364% | -0.514% | +16.904% | +13.508% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 2.489% | -5.834% | +6.012% | +14.104% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 2.406% | +1.812% | +4.744% | +5.102% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.939% | +1.692% | -1.301% | +1.670% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.982% | +0.731% | +4.634% | +8.204% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.218% | -0.627% | +2.426% | +11.291% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 2.747% | -0.539% | +0.949% | +22.394% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.191% | +0.874% | +1.875% | +21.684% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.712% | +0.796% | +2.576% | +21.208% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.466% | -0.238% | +9.872% | +12.703% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.283% | +0.103% | +0.212% | +10.348% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.139% | +0.362% | +10.556% | +5.718% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.115% | +0.413% | +1.976% | +5.581% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.935% | +0.216% | +9.948% | +14.090% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.363% | -3.551% | +2.063% | +13.731% | +-----+------------------------+--------+------------+------------+------------+ | :-( | regex_dna| 0.319% | -2.095% | -3.035% | +12.260% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.445% | +0.270% | -4.246% | +4.998% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.471% | +0.131% | +4.012% | +8.762% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.284% | +1.832% | +8.686% | +16.214% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.632% | +0.394% | -3.378% | +5.656% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.532% | -0.792% | +26.189% | +9.854% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.460% | +1.843% | +4.115% | +4.854% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.718% | +1.337% | +14.316% | +8.707% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.625% | +2.926% | -3.672% | +0.284% | +-----+------------------------+--------+------------+------------+------------+ | :-) | spectral_norm| 1.704% | +5.220% | +2.864% | +5.878% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.876% | +1.516% | +7.980% | +5.933% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.617% | -0.286% | +5.749% | +6.841% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.252% | -4.179% | +17.558% | +10.105% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 1.944% | -0.893% | +11.707% | +8.532% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.412% | -0.183% | +9.198% | +6.688% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.625% | +0.058% | +11.424% | +7.443% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 4.984% | +1.071% | +10.638% | +10.319% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 4.365% | -0.351% | +18.015% | +14.077% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.237% | +0.406% | +5.927% | +7.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.857% | +0.556% | +2.456% | +0.303% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.307% | -1.867% | +4.198% | +23.336% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 3.710% | +3.564% | -3.067% | +15.126% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.105% | -0.400% | +6.377% | +8.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.932% | -2.204% | +3.206% | +11.354% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.357% | +0.354% | +2.973% | +8.557% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.178% | +1.844% | -6.722% | +12.070% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.134% | -2.007% | +4.860% | +11.230% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-down-2-up-62-flat-results-for-python-master-branch-2017-12-21 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Fri Dec 22 00:43:13 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 22 Dec 2017 05:43:13 -0000 Subject: [Python-checkins] remove the dynload_next.c file (closes bpo-32386) (#4957) Message-ID: https://github.com/python/cpython/commit/62ed6be8da5fd1142f838582ecdb338af539e85b commit: 62ed6be8da5fd1142f838582ecdb338af539e85b branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-21T21:43:09-08:00 summary: remove the dynload_next.c file (closes bpo-32386) (#4957) files: D Python/dynload_next.c M configure M configure.ac diff --git a/Python/dynload_next.c b/Python/dynload_next.c deleted file mode 100644 index 83a8b2bb319..00000000000 --- a/Python/dynload_next.c +++ /dev/null @@ -1,111 +0,0 @@ - -/* Support for dynamic loading of extension modules on Mac OS X -** All references to "NeXT" are for historical reasons. -*/ - -#include "Python.h" -#include "importdl.h" - -#include - -const char *_PyImport_DynLoadFiletab[] = {".so", NULL}; - -/* -** Python modules are Mach-O MH_BUNDLE files. The best way to load these -** is each in a private namespace, so you can load, say, a module bar and a -** module foo.bar. If we load everything in the global namespace the two -** initbar() symbols will conflict. -** However, it seems some extension packages depend upon being able to access -** each others' global symbols. There seems to be no way to eat our cake and -** have it, so the USE_DYLD_GLOBAL_NAMESPACE define determines which behaviour -** you get. -*/ - -#ifdef USE_DYLD_GLOBAL_NAMESPACE -#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR -#else -#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \ - NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE -#endif -dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, - const char *shortname, - const char *pathname, FILE *fp) -{ - dl_funcptr p = NULL; - char funcname[258]; - NSObjectFileImageReturnCode rc; - NSObjectFileImage image; - NSModule newModule; - NSSymbol theSym; - const char *errString; - char errBuf[512]; - - PyOS_snprintf(funcname, sizeof(funcname), "_%.20s_%.200s", prefix, shortname); - -#ifdef USE_DYLD_GLOBAL_NAMESPACE - if (NSIsSymbolNameDefined(funcname)) { - theSym = NSLookupAndBindSymbol(funcname); - p = (dl_funcptr)NSAddressOfSymbol(theSym); - return p; - } -#endif - rc = NSCreateObjectFileImageFromFile(pathname, &image); - switch(rc) { - default: - case NSObjectFileImageFailure: - case NSObjectFileImageFormat: - /* for these a message is printed on stderr by dyld */ - errString = "Can't create object file image"; - break; - case NSObjectFileImageSuccess: - errString = NULL; - break; - case NSObjectFileImageInappropriateFile: - errString = "Inappropriate file type for dynamic loading"; - break; - case NSObjectFileImageArch: - errString = "Wrong CPU type in object file"; - break; - case NSObjectFileImageAccess: - errString = "Can't read object file (no access)"; - break; - } - if (errString == NULL) { - newModule = NSLinkModule(image, pathname, LINKOPTIONS); - if (newModule == NULL) { - int errNo; - const char *fileName, *moreErrorStr; - NSLinkEditErrors c; - NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr ); - PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", - fileName, moreErrorStr); - errString = errBuf; - } - } - if (errString != NULL) { - PyErr_SetString(PyExc_ImportError, errString); - return NULL; - } -#ifdef USE_DYLD_GLOBAL_NAMESPACE - if (!NSIsSymbolNameDefined(funcname)) { - /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */ - /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ - PyErr_Format(PyExc_ImportError, - "Loaded module does not contain symbol %.200s", - funcname); - return NULL; - } - theSym = NSLookupAndBindSymbol(funcname); -#else - theSym = NSLookupSymbolInModule(newModule, funcname); - if ( theSym == NULL ) { - /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ - PyErr_Format(PyExc_ImportError, - "Loaded module does not contain symbol %.200s", - funcname); - return NULL; - } -#endif - p = (dl_funcptr)NSAddressOfSymbol(theSym); - return p; -} diff --git a/configure b/configure index 24ae2564091..2728f67b577 100755 --- a/configure +++ b/configure @@ -778,6 +778,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -889,6 +890,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1141,6 +1143,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1278,7 +1289,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1431,6 +1442,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -9125,7 +9137,7 @@ then LDCXXSHARED='$(CXX) -shared' else LDSHARED='$(CC) -b' - LDCXXSHARED='$(CXX) -shared' + LDCXXSHARED='$(CXX) -b' fi ;; Darwin/1.3*) LDSHARED='$(CC) -bundle' @@ -9872,6 +9884,7 @@ fi + if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. @@ -11099,8 +11112,6 @@ then fi ;; hp*|HP*) DYNLOADFILE="dynload_hpux.o";; - # Use dynload_next.c only on 10.2 and below, which don't have native dlopen() - Darwin/[0156]\..*) DYNLOADFILE="dynload_next.o";; *) # use dynload_shlib.c and dlopen() if we have it; otherwise stub # out any dynamic loading diff --git a/configure.ac b/configure.ac index 48eaa2ae7f3..027109c65d2 100644 --- a/configure.ac +++ b/configure.ac @@ -3373,8 +3373,6 @@ then fi ;; hp*|HP*) DYNLOADFILE="dynload_hpux.o";; - # Use dynload_next.c only on 10.2 and below, which don't have native dlopen() - Darwin/@<:@0156@:>@\..*) DYNLOADFILE="dynload_next.o";; *) # use dynload_shlib.c and dlopen() if we have it; otherwise stub # out any dynamic loading From solipsis at pitrou.net Fri Dec 22 04:07:22 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 22 Dec 2017 09:07:22 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171222090722.20654.2C7AF97E47B5C555@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog6WIHip', '--timeout', '7200'] From webhook-mailer at python.org Fri Dec 22 15:18:41 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 22 Dec 2017 20:18:41 -0000 Subject: [Python-checkins] bpo-24960: use pkgutil.get_data in lib2to3 to read pickled grammar files (#4977) Message-ID: https://github.com/python/cpython/commit/8a5877165e993afb2633cd48da5222326d3f6e0e commit: 8a5877165e993afb2633cd48da5222326d3f6e0e branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-22T12:18:33-08:00 summary: bpo-24960: use pkgutil.get_data in lib2to3 to read pickled grammar files (#4977) This is more complicated than it should be because we need to preserve the useful mtime-based regeneration feature that lib2to3.pgen2.driver.load_grammar has. We only look for the pickled grammar file with pkgutil.get_data and only if the source file does not exist. files: A Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst M Lib/lib2to3/pgen2/driver.py M Lib/lib2to3/pgen2/grammar.py M Lib/lib2to3/pygram.py M Lib/lib2to3/tests/test_parser.py diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py index e5e4824c008..95c6692cf7c 100644 --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -20,6 +20,7 @@ import io import os import logging +import pkgutil import sys # Pgen imports @@ -140,6 +141,26 @@ def _newer(a, b): return os.path.getmtime(a) >= os.path.getmtime(b) +def load_packaged_grammar(package, grammar_source): + """Normally, loads a pickled grammar by doing + pkgutil.get_data(package, pickled_grammar) + where *pickled_grammar* is computed from *grammar_source* by adding the + Python version and using a ``.pickle`` extension. + + However, if *grammar_source* is an extant file, load_grammar(grammar_source) + is called instead. This facilities using a packaged grammar file when needed + but preserves load_grammar's automatic regeneration behavior when possible. + + """ + if os.path.isfile(grammar_source): + return load_grammar(grammar_source) + pickled_name = _generate_pickle_name(os.path.basename(grammar_source)) + data = pkgutil.get_data(package, pickled_name) + g = grammar.Grammar() + g.loads(data) + return g + + def main(*args): """Main program, when run as a script: produce grammar pickle files. diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py index c10dcfa9ac2..088c58bfa99 100644 --- a/Lib/lib2to3/pgen2/grammar.py +++ b/Lib/lib2to3/pgen2/grammar.py @@ -108,6 +108,10 @@ def load(self, filename): d = pickle.load(f) self.__dict__.update(d) + def loads(self, pkl): + """Load the grammar tables from a pickle bytes object.""" + self.__dict__.update(pickle.loads(pkl)) + def copy(self): """ Copy the grammar. diff --git a/Lib/lib2to3/pygram.py b/Lib/lib2to3/pygram.py index 01fa1087115..919624eb399 100644 --- a/Lib/lib2to3/pygram.py +++ b/Lib/lib2to3/pygram.py @@ -29,12 +29,12 @@ def __init__(self, grammar): setattr(self, name, symbol) -python_grammar = driver.load_grammar(_GRAMMAR_FILE) +python_grammar = driver.load_packaged_grammar("lib2to3", _GRAMMAR_FILE) python_symbols = Symbols(python_grammar) python_grammar_no_print_statement = python_grammar.copy() del python_grammar_no_print_statement.keywords["print"] -pattern_grammar = driver.load_grammar(_PATTERN_GRAMMAR_FILE) +pattern_grammar = driver.load_packaged_grammar("lib2to3", _PATTERN_GRAMMAR_FILE) pattern_symbols = Symbols(pattern_grammar) diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py index dc94a69036a..ed1ef836463 100644 --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -12,7 +12,10 @@ from test.support import verbose # Python imports +import importlib +import operator import os +import pickle import shutil import subprocess import sys @@ -99,6 +102,18 @@ def test_load_grammar_from_subprocess(self): finally: shutil.rmtree(tmpdir) + def test_load_packaged_grammar(self): + modname = __name__ + '.load_test' + class MyLoader: + def get_data(self, where): + return pickle.dumps({'elephant': 19}) + class MyModule: + __file__ = 'parsertestmodule' + __spec__ = importlib.util.spec_from_loader(modname, MyLoader()) + sys.modules[modname] = MyModule() + self.addCleanup(operator.delitem, sys.modules, modname) + g = pgen2_driver.load_packaged_grammar(modname, 'Grammar.txt') + self.assertEqual(g.elephant, 19) class GrammarTest(support.TestCase): diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst b/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst new file mode 100644 index 00000000000..6f9d83c5772 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst @@ -0,0 +1,3 @@ +2to3 and lib2to3 can now read pickled grammar files using pkgutil.get_data() +rather than probing the filesystem. This lets 2to3 and lib2to3 work when run +from a zipfile. From webhook-mailer at python.org Fri Dec 22 15:51:48 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 22 Dec 2017 20:51:48 -0000 Subject: [Python-checkins] bpo-24960: use pkgutil.get_data in lib2to3 to read pickled grammar files (GH-4977) (#4979) Message-ID: https://github.com/python/cpython/commit/c1b8eb8006ed79bbf91dc7d89918f39cc10b4fe6 commit: c1b8eb8006ed79bbf91dc7d89918f39cc10b4fe6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2017-12-22T12:51:46-08:00 summary: bpo-24960: use pkgutil.get_data in lib2to3 to read pickled grammar files (GH-4977) (#4979) This is more complicated than it should be because we need to preserve the useful mtime-based regeneration feature that lib2to3.pgen2.driver.load_grammar has. We only look for the pickled grammar file with pkgutil.get_data and only if the source file does not exist. (cherry picked from commit 8a5877165e993afb2633cd48da5222326d3f6e0e) files: A Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst M Lib/lib2to3/pgen2/driver.py M Lib/lib2to3/pgen2/grammar.py M Lib/lib2to3/pygram.py M Lib/lib2to3/tests/test_parser.py diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py index a27b9cb40b0..f2b521bcb36 100644 --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -20,6 +20,7 @@ import io import os import logging +import pkgutil import sys # Pgen imports @@ -143,6 +144,26 @@ def _newer(a, b): return os.path.getmtime(a) >= os.path.getmtime(b) +def load_packaged_grammar(package, grammar_source): + """Normally, loads a pickled grammar by doing + pkgutil.get_data(package, pickled_grammar) + where *pickled_grammar* is computed from *grammar_source* by adding the + Python version and using a ``.pickle`` extension. + + However, if *grammar_source* is an extant file, load_grammar(grammar_source) + is called instead. This facilities using a packaged grammar file when needed + but preserves load_grammar's automatic regeneration behavior when possible. + + """ + if os.path.isfile(grammar_source): + return load_grammar(grammar_source) + pickled_name = _generate_pickle_name(os.path.basename(grammar_source)) + data = pkgutil.get_data(package, pickled_name) + g = grammar.Grammar() + g.loads(data) + return g + + def main(*args): """Main program, when run as a script: produce grammar pickle files. diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py index 321e25ebd78..669de85993e 100644 --- a/Lib/lib2to3/pgen2/grammar.py +++ b/Lib/lib2to3/pgen2/grammar.py @@ -108,6 +108,10 @@ def load(self, filename): d = pickle.load(f) self.__dict__.update(d) + def loads(self, pkl): + """Load the grammar tables from a pickle bytes object.""" + self.__dict__.update(pickle.loads(pkl)) + def copy(self): """ Copy the grammar. diff --git a/Lib/lib2to3/pygram.py b/Lib/lib2to3/pygram.py index 01fa1087115..919624eb399 100644 --- a/Lib/lib2to3/pygram.py +++ b/Lib/lib2to3/pygram.py @@ -29,12 +29,12 @@ def __init__(self, grammar): setattr(self, name, symbol) -python_grammar = driver.load_grammar(_GRAMMAR_FILE) +python_grammar = driver.load_packaged_grammar("lib2to3", _GRAMMAR_FILE) python_symbols = Symbols(python_grammar) python_grammar_no_print_statement = python_grammar.copy() del python_grammar_no_print_statement.keywords["print"] -pattern_grammar = driver.load_grammar(_PATTERN_GRAMMAR_FILE) +pattern_grammar = driver.load_packaged_grammar("lib2to3", _PATTERN_GRAMMAR_FILE) pattern_symbols = Symbols(pattern_grammar) diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py index 3f7ab9714e3..0a139507b8d 100644 --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -12,7 +12,10 @@ from test.support import verbose # Python imports +import importlib +import operator import os +import pickle import shutil import subprocess import sys @@ -99,6 +102,18 @@ def test_load_grammar_from_subprocess(self): finally: shutil.rmtree(tmpdir) + def test_load_packaged_grammar(self): + modname = __name__ + '.load_test' + class MyLoader: + def get_data(self, where): + return pickle.dumps({'elephant': 19}) + class MyModule: + __file__ = 'parsertestmodule' + __spec__ = importlib.util.spec_from_loader(modname, MyLoader()) + sys.modules[modname] = MyModule() + self.addCleanup(operator.delitem, sys.modules, modname) + g = pgen2_driver.load_packaged_grammar(modname, 'Grammar.txt') + self.assertEqual(g.elephant, 19) class GrammarTest(support.TestCase): diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst b/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst new file mode 100644 index 00000000000..6f9d83c5772 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst @@ -0,0 +1,3 @@ +2to3 and lib2to3 can now read pickled grammar files using pkgutil.get_data() +rather than probing the filesystem. This lets 2to3 and lib2to3 work when run +from a zipfile. From webhook-mailer at python.org Fri Dec 22 15:52:13 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 22 Dec 2017 20:52:13 -0000 Subject: [Python-checkins] [2.7] bpo-24960: use pkgutil.get_data in lib2to3 to read pickled grammar files (GH-4977) (#4980) Message-ID: https://github.com/python/cpython/commit/770a802df7057bcf0d72bbc01026fac8d396e1b3 commit: 770a802df7057bcf0d72bbc01026fac8d396e1b3 branch: 2.7 author: Benjamin Peterson committer: GitHub date: 2017-12-22T12:52:10-08:00 summary: [2.7] bpo-24960: use pkgutil.get_data in lib2to3 to read pickled grammar files (GH-4977) (#4980) This is more complicated than it should be because we need to preserve the useful mtime-based regeneration feature that lib2to3.pgen2.driver.load_grammar has. We only look for the pickled grammar file with pkgutil.get_data and only if the source file does not exist.. (cherry picked from commit 8a5877165e993afb2633cd48da5222326d3f6e0e) files: A Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst M Lib/lib2to3/pgen2/driver.py M Lib/lib2to3/pgen2/grammar.py M Lib/lib2to3/pygram.py M Lib/lib2to3/tests/test_parser.py diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py index ce601bb04f9..e8d10e47dba 100644 --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -19,6 +19,7 @@ import codecs import os import logging +import pkgutil import StringIO import sys @@ -143,6 +144,26 @@ def _newer(a, b): return os.path.getmtime(a) >= os.path.getmtime(b) +def load_packaged_grammar(package, grammar_source): + """Normally, loads a pickled grammar by doing + pkgutil.get_data(package, pickled_grammar) + where *pickled_grammar* is computed from *grammar_source* by adding the + Python version and using a ``.pickle`` extension. + + However, if *grammar_source* is an extant file, load_grammar(grammar_source) + is called instead. This facilities using a packaged grammar file when needed + but preserves load_grammar's automatic regeneration behavior when possible. + + """ + if os.path.isfile(grammar_source): + return load_grammar(grammar_source) + pickled_name = _generate_pickle_name(os.path.basename(grammar_source)) + data = pkgutil.get_data(package, pickled_name) + g = grammar.Grammar() + g.loads(data) + return g + + def main(*args): """Main program, when run as a script: produce grammar pickle files. diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py index 75255e9c013..0b6d86b6799 100644 --- a/Lib/lib2to3/pgen2/grammar.py +++ b/Lib/lib2to3/pgen2/grammar.py @@ -109,6 +109,10 @@ def load(self, filename): f.close() self.__dict__.update(d) + def loads(self, pkl): + """Load the grammar tables from a pickle bytes object.""" + self.__dict__.update(pickle.loads(pkl)) + def copy(self): """ Copy the grammar. diff --git a/Lib/lib2to3/pygram.py b/Lib/lib2to3/pygram.py index 621ff24c954..7e67e4a8678 100644 --- a/Lib/lib2to3/pygram.py +++ b/Lib/lib2to3/pygram.py @@ -29,12 +29,12 @@ def __init__(self, grammar): setattr(self, name, symbol) -python_grammar = driver.load_grammar(_GRAMMAR_FILE) +python_grammar = driver.load_packaged_grammar("lib2to3", _GRAMMAR_FILE) python_symbols = Symbols(python_grammar) python_grammar_no_print_statement = python_grammar.copy() del python_grammar_no_print_statement.keywords["print"] -pattern_grammar = driver.load_grammar(_PATTERN_GRAMMAR_FILE) +pattern_grammar = driver.load_packaged_grammar("lib2to3", _PATTERN_GRAMMAR_FILE) pattern_symbols = Symbols(pattern_grammar) diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py index ebf84418fe6..d2254f13e09 100644 --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -11,11 +11,14 @@ from .support import driver, test_dir # Python imports +import operator import os +import pickle import shutil import subprocess import sys import tempfile +import types import unittest # Local imports @@ -97,6 +100,18 @@ def test_load_grammar_from_subprocess(self): finally: shutil.rmtree(tmpdir) + def test_load_packaged_grammar(self): + modname = __name__ + '.load_test' + class MyLoader: + def get_data(self, where): + return pickle.dumps({'elephant': 19}) + class MyModule(types.ModuleType): + __file__ = 'parsertestmodule' + __loader__ = MyLoader() + sys.modules[modname] = MyModule(modname) + self.addCleanup(operator.delitem, sys.modules, modname) + g = pgen2_driver.load_packaged_grammar(modname, 'Grammar.txt') + self.assertEqual(g.elephant, 19) class GrammarTest(support.TestCase): diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst b/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst new file mode 100644 index 00000000000..6f9d83c5772 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2017-12-22-09-25-51.bpo-24960.TGdAgO.rst @@ -0,0 +1,3 @@ +2to3 and lib2to3 can now read pickled grammar files using pkgutil.get_data() +rather than probing the filesystem. This lets 2to3 and lib2to3 work when run +from a zipfile. From lp_benchmark_robot at intel.com Fri Dec 22 20:27:28 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 22 Dec 2017 17:27:28 -0800 Subject: [Python-checkins] [2 down, 2 up, 61 flat] Results for Python (master branch) 2017-12-22 Message-ID: <380b6900-7fd7-4149-a553-786b8f7807d9@orsmsx103.amr.corp.intel.com> Results for project python/master, build date: 2017-12-22 03:03:41-08:00. - commit: 62ed6be - previous commit: a8d25a1 - revision date: 2017-12-21 21:43:09-08:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.953% | -0.480% | +5.023% | +7.681% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.857% | +0.714% | +23.528% | +11.332% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.121% | +0.372% | +25.581% | +8.909% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.362% | +0.020% | +22.230% | +10.548% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.092% | -0.799% | +7.435% | +9.511% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.528% | -0.576% | +9.957% | +10.973% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.586% | -0.588% | +5.593% | +11.332% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.812% | +0.296% | -0.509% | +7.364% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.095% | -1.152% | +9.978% | +16.795% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.653% | +1.684% | +13.795% | +12.579% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.043% | -0.749% | +3.057% | +7.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.530% | -0.361% | +4.406% | +4.089% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.834% | -0.677% | +1.583% | +7.833% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.305% | -0.476% | +12.398% | +7.753% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.687% | +0.490% | +8.679% | +8.983% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 1.195% | -1.499% | +5.395% | +10.882% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.678% | -0.087% | +9.874% | +10.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.529% | -1.755% | +5.783% | +11.137% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.448% | +0.582% | +3.934% | +7.681% | +-----+------------------------+--------+------------+------------+------------+ | :-) | json_loads| 1.408% | +5.817% | +1.131% | +12.883% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.372% | +0.182% | +7.462% | +10.816% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.676% | +0.121% | +47.019% | +11.866% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.467% | +1.180% | +8.432% | +12.075% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.467% | -0.065% | +16.849% | +13.252% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 1.972% | -2.054% | +4.081% | +15.171% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.962% | -1.147% | +3.652% | +5.847% | +-----+------------------------+--------+------------+------------+------------+ | :-( | nbody| 0.867% | -3.918% | -5.270% | +2.145% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.739% | -0.105% | +4.534% | +7.498% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 0.945% | +1.131% | +3.529% | +9.302% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.254% | +0.726% | +1.668% | +20.036% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.202% | +0.113% | +1.986% | +24.351% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.637% | +0.606% | +3.167% | +22.321% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 1.530% | +1.838% | +11.529% | +8.889% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.247% | -0.073% | +0.139% | +10.508% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.138% | +0.354% | +10.873% | +4.762% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.107% | +0.328% | +2.298% | +4.927% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.249% | +0.433% | +10.338% | +13.187% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.702% | -0.498% | +1.576% | +12.340% | +-----+------------------------+--------+------------+------------+------------+ | :-) | regex_dna| 0.242% | +2.600% | -0.355% | +9.734% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.939% | -1.733% | -6.053% | +7.236% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.583% | +2.662% | +6.567% | +6.690% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.532% | +0.180% | +8.851% | +14.433% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.598% | -1.569% | -5.000% | +5.614% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.362% | -0.719% | +25.658% | +9.082% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.312% | -0.062% | +4.056% | +4.602% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.786% | -0.745% | +13.678% | +7.473% | +-----+------------------------+--------+------------+------------+------------+ | :-( | scimark_sparse_mat_mult| 0.712% | -3.698% | -7.506% | -0.025% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.491% | -0.350% | +2.524% | +4.034% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.572% | -1.665% | +6.448% | +6.796% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.829% | +0.499% | +6.219% | +5.287% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.956% | +2.141% | +19.322% | +7.601% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 1.887% | +0.201% | +11.884% | +7.490% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.527% | +0.008% | +9.206% | +6.634% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.646% | -0.099% | +11.336% | +8.535% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.270% | +0.481% | +11.068% | +8.879% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 4.835% | -0.977% | +17.214% | +15.687% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.083% | +0.500% | +6.398% | +6.532% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.969% | +0.080% | +2.534% | -1.382% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.021% | +0.216% | +4.405% | +22.975% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 6.748% | -0.028% | -3.096% | +16.982% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.062% | +0.708% | +7.039% | +7.005% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.518% | -0.919% | +2.317% | +11.179% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.144% | +0.004% | +2.976% | +8.597% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.517% | +0.459% | -6.232% | +10.680% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.347% | -0.727% | +4.168% | +10.832% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/2-down-2-up-61-flat-results-for-python-master-branch-2017-12-22 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Fri Dec 22 23:48:16 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 23 Dec 2017 04:48:16 -0000 Subject: [Python-checkins] correct wording (#4983) Message-ID: https://github.com/python/cpython/commit/d11e8e0d11c759cd0f96aebb59de914e4d62b8cd commit: d11e8e0d11c759cd0f96aebb59de914e4d62b8cd branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-22T20:48:13-08:00 summary: correct wording (#4983) files: M Lib/lib2to3/pgen2/driver.py diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py index 95c6692cf7c..cbc58e759d5 100644 --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -148,7 +148,7 @@ def load_packaged_grammar(package, grammar_source): Python version and using a ``.pickle`` extension. However, if *grammar_source* is an extant file, load_grammar(grammar_source) - is called instead. This facilities using a packaged grammar file when needed + is called instead. This facilitates using a packaged grammar file when needed but preserves load_grammar's automatic regeneration behavior when possible. """ From webhook-mailer at python.org Sat Dec 23 00:49:38 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 23 Dec 2017 05:49:38 -0000 Subject: [Python-checkins] correct wording (GH-4983) (#4984) Message-ID: https://github.com/python/cpython/commit/6ba06377276fca9dc703c5139e2f0ea0ff03636a commit: 6ba06377276fca9dc703c5139e2f0ea0ff03636a branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2017-12-22T21:49:35-08:00 summary: correct wording (GH-4983) (#4984) (cherry picked from commit d11e8e0d11c759cd0f96aebb59de914e4d62b8cd) files: M Lib/lib2to3/pgen2/driver.py diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py index f2b521bcb36..c5580a33d39 100644 --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -151,7 +151,7 @@ def load_packaged_grammar(package, grammar_source): Python version and using a ``.pickle`` extension. However, if *grammar_source* is an extant file, load_grammar(grammar_source) - is called instead. This facilities using a packaged grammar file when needed + is called instead. This facilitates using a packaged grammar file when needed but preserves load_grammar's automatic regeneration behavior when possible. """ From webhook-mailer at python.org Sat Dec 23 00:49:52 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 23 Dec 2017 05:49:52 -0000 Subject: [Python-checkins] correct wording (GH-4983) (#4985) Message-ID: https://github.com/python/cpython/commit/8b9995f2ae0f9496de8a1a64a00d0681edd692bf commit: 8b9995f2ae0f9496de8a1a64a00d0681edd692bf branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2017-12-22T21:49:49-08:00 summary: correct wording (GH-4983) (#4985) (cherry picked from commit d11e8e0d11c759cd0f96aebb59de914e4d62b8cd) files: M Lib/lib2to3/pgen2/driver.py diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py index e8d10e47dba..a5133309c6c 100644 --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -151,7 +151,7 @@ def load_packaged_grammar(package, grammar_source): Python version and using a ``.pickle`` extension. However, if *grammar_source* is an extant file, load_grammar(grammar_source) - is called instead. This facilities using a packaged grammar file when needed + is called instead. This facilitates using a packaged grammar file when needed but preserves load_grammar's automatic regeneration behavior when possible. """ From webhook-mailer at python.org Sat Dec 23 02:39:06 2017 From: webhook-mailer at python.org (Mariatta) Date: Sat, 23 Dec 2017 07:39:06 -0000 Subject: [Python-checkins] bpo-26439: Convert %s in Lib/ctypes/_aix.py to f-strings. (GH-4986) Message-ID: https://github.com/python/cpython/commit/c0919c27c6442aa147ae559a936b1b8deb4ee783 commit: c0919c27c6442aa147ae559a936b1b8deb4ee783 branch: master author: Mariatta committer: GitHub date: 2017-12-22T23:39:03-08:00 summary: bpo-26439: Convert %s in Lib/ctypes/_aix.py to f-strings. (GH-4986) files: M Lib/ctypes/_aix.py M Lib/ctypes/util.py diff --git a/Lib/ctypes/_aix.py b/Lib/ctypes/_aix.py index 5c4d8d9cc91..61af9423ac5 100644 --- a/Lib/ctypes/_aix.py +++ b/Lib/ctypes/_aix.py @@ -105,7 +105,7 @@ def get_ld_headers(file): # 2. If "INDEX" in occurs in a following line - return ld_header # 3. get info (lines starting with [0-9]) ldr_headers = [] - p = Popen(["/usr/bin/dump", "-X%s" % AIX_ABI, "-H", file], + p = Popen(["/usr/bin/dump", f"-X{AIX_ABI}", "-H", file], universal_newlines=True, stdout=PIPE, stderr=DEVNULL) # be sure to read to the end-of-file - getting all entries while True: @@ -140,7 +140,7 @@ def get_one_match(expr, lines): When there is a match, strip leading "[" and trailing "]" """ # member names in the ld_headers output are between square brackets - expr = r'\[(%s)\]' % expr + expr = rf'\[({expr})\]' matches = list(filter(None, (re.search(expr, line) for line in lines))) if len(matches) == 1: return matches[0].group(1) @@ -197,8 +197,8 @@ def get_version(name, members): # any combination of additional 'dot' digits pairs are accepted # anything more than libFOO.so.digits.digits.digits # should be seen as a member name outside normal expectations - exprs = [r'lib%s\.so\.[0-9]+[0-9.]*' % name, - r'lib%s_?64\.so\.[0-9]+[0-9.]*' % name] + exprs = [rf'lib{name}\.so\.[0-9]+[0-9.]*', + rf'lib{name}_?64\.so\.[0-9]+[0-9.]*'] for expr in exprs: versions = [] for line in members: @@ -219,12 +219,12 @@ def get_member(name, members): and finally, legacy AIX naming scheme. """ # look first for a generic match - prepend lib and append .so - expr = r'lib%s\.so' % name + expr = rf'lib{name}\.so' member = get_one_match(expr, members) if member: return member elif AIX_ABI == 64: - expr = r'lib%s64\.so' % name + expr = rf'lib{name}64\.so' member = get_one_match(expr, members) if member: return member @@ -277,7 +277,7 @@ def find_shared(paths, name): continue # "lib" is prefixed to emulate compiler name resolution, # e.g., -lc to libc - base = 'lib%s.a' % name + base = f'lib{name}.a' archive = path.join(dir, base) if path.exists(archive): members = get_shared(get_ld_headers(archive)) @@ -308,7 +308,7 @@ def find_library(name): libpaths = get_libpaths() (base, member) = find_shared(libpaths, name) if base != None: - return "%s(%s)" % (base, member) + return f"{base}({member})" # To get here, a member in an archive has not been found # In other words, either: @@ -319,7 +319,7 @@ def find_library(name): # Note, the installation must prepare a link from a .so # to a versioned file # This is common practice by GNU libtool on other platforms - soname = "lib%s.so" % name + soname = f"lib{name}.so" for dir in libpaths: # /lib is a symbolic link to /usr/lib, skip it if dir == "/lib": diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index e837abba5c8..5e8b31a8546 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -337,18 +337,18 @@ def test(): elif sys.platform.startswith("aix"): from ctypes import CDLL if sys.maxsize < 2**32: - print("Using CDLL(name, os.RTLD_MEMBER): %s" % CDLL("libc.a(shr.o)", os.RTLD_MEMBER)) - print("Using cdll.LoadLibrary(): %s" % cdll.LoadLibrary("libc.a(shr.o)")) + print(f"Using CDLL(name, os.RTLD_MEMBER): {CDLL('libc.a(shr.o)', os.RTLD_MEMBER)}") + print(f"Using cdll.LoadLibrary(): {cdll.LoadLibrary('libc.a(shr.o)')}") # librpm.so is only available as 32-bit shared library print(find_library("rpm")) print(cdll.LoadLibrary("librpm.so")) else: - print("Using CDLL(name, os.RTLD_MEMBER): %s" % CDLL("libc.a(shr_64.o)", os.RTLD_MEMBER)) - print("Using cdll.LoadLibrary(): %s" % cdll.LoadLibrary("libc.a(shr_64.o)")) - print("crypt\t:: %s" % find_library("crypt")) - print("crypt\t:: %s" % cdll.LoadLibrary(find_library("crypt"))) - print("crypto\t:: %s" % find_library("crypto")) - print("crypto\t:: %s" % cdll.LoadLibrary(find_library("crypto"))) + print(f"Using CDLL(name, os.RTLD_MEMBER): {CDLL('libc.a(shr_64.o)', os.RTLD_MEMBER)}") + print(f"Using cdll.LoadLibrary(): {cdll.LoadLibrary('libc.a(shr_64.o)')}") + print(f"crypt\t:: {find_library('crypt')}") + print(f"crypt\t:: {cdll.LoadLibrary(find_library('crypt'))}") + print(f"crypto\t:: {find_library('crypto')}") + print(f"crypto\t:: {cdll.LoadLibrary(find_library('crypto'))}") else: print(cdll.LoadLibrary("libm.so")) print(cdll.LoadLibrary("libcrypt.so")) From solipsis at pitrou.net Sat Dec 23 04:10:09 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 23 Dec 2017 09:10:09 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=2 Message-ID: <20171223091009.127512.D45F899C83953413@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, 0, -2] memory blocks, sum=-2 test_multiprocessing_spawn leaked [-1, -1, 2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogzL7Z1C', '--timeout', '7200'] From webhook-mailer at python.org Sat Dec 23 12:44:33 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 23 Dec 2017 17:44:33 -0000 Subject: [Python-checkins] bpo-32357: Fix tests in refleak mode (#4989) Message-ID: https://github.com/python/cpython/commit/558aa30f7971e087c4a00b1f49cc2ef3195c01ca commit: 558aa30f7971e087c4a00b1f49cc2ef3195c01ca branch: master author: Yury Selivanov committer: GitHub date: 2017-12-23T12:44:29-05:00 summary: bpo-32357: Fix tests in refleak mode (#4989) files: M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_pep492.py diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index aefa33ba251..e5e41fc1a87 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -66,6 +66,20 @@ def _test_get_event_loop_new_process__sub_proc(): return loop.run_until_complete(doit()) +class CoroLike: + def send(self, v): + pass + + def throw(self, *exc): + pass + + def close(self): + pass + + def __await__(self): + pass + + ONLYCERT = data_file('ssl_cert.pem') ONLYKEY = data_file('ssl_key.pem') SIGNED_CERTFILE = data_file('keycert3.pem') @@ -2365,20 +2379,7 @@ def test_coroutine_like_object_debug_formatting(self): # collections.abc.Coroutine, but lack cr_core or gi_code attributes # (such as ones compiled with Cython). - class Coro: - def send(self, v): - pass - - def throw(self, *exc): - pass - - def close(self): - pass - - def __await__(self): - pass - - coro = Coro() + coro = CoroLike() coro.__name__ = 'AAA' self.assertTrue(asyncio.iscoroutine(coro)) self.assertEqual(coroutines._format_coroutine(coro), 'AAA()') @@ -2389,10 +2390,10 @@ def __await__(self): coro.cr_running = True self.assertEqual(coroutines._format_coroutine(coro), 'BBB() running') - coro = Coro() + coro = CoroLike() # Some coroutines might not have '__name__', such as # built-in async_gen.asend(). - self.assertEqual(coroutines._format_coroutine(coro), 'Coro()') + self.assertEqual(coroutines._format_coroutine(coro), 'CoroLike()') class TimerTests(unittest.TestCase): diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py index 8dd0c25e7cf..289f7e59db7 100644 --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -10,6 +10,21 @@ from test.test_asyncio import utils as test_utils +# 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 + + class BaseTest(test_utils.TestCase): def setUp(self): @@ -99,13 +114,6 @@ def test_iscoroutine(self): finally: f.close() # silence warning - # 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 - self.assertTrue(asyncio.iscoroutine(FakeCoro())) def test_iscoroutinefunction(self): From webhook-mailer at python.org Sat Dec 23 15:04:18 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 23 Dec 2017 20:04:18 -0000 Subject: [Python-checkins] bpo-32415: Add asyncio.Task.get_loop() and Future.get_loop() (#4992) Message-ID: https://github.com/python/cpython/commit/ca9b36cd1a384e5ecb56d9df9a59144240353ef0 commit: ca9b36cd1a384e5ecb56d9df9a59144240353ef0 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-23T15:04:15-05:00 summary: bpo-32415: Add asyncio.Task.get_loop() and Future.get_loop() (#4992) files: A Misc/NEWS.d/next/Library/2017-12-23-12-45-00.bpo-32415.YufXTU.rst M Doc/library/asyncio-task.rst M Lib/asyncio/base_events.py M Lib/asyncio/futures.py M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c M Modules/clinic/_asynciomodule.c.h diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index d85dddfa02e..71dbe06c899 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -306,6 +306,12 @@ Future If the future is already done when this method is called, raises :exc:`InvalidStateError`. + .. method:: get_loop() + + Return the event loop the future object is bound to. + + .. versionadded:: 3.7 + Example: Future with run_until_complete() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 2ab8a76e0c5..96cc4f02588 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -145,7 +145,7 @@ def _run_until_complete_cb(fut): # Issue #22429: run_forever() already finished, no need to # stop it. return - fut._loop.stop() + futures._get_loop(fut).stop() class Server(events.AbstractServer): diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index b310962f9fe..24843c016a7 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -105,6 +105,10 @@ def __del__(self): context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) + def get_loop(self): + """Return the event loop the Future is bound to.""" + return self._loop + def cancel(self): """Cancel the future and schedule callbacks. @@ -249,6 +253,18 @@ def __iter__(self): _PyFuture = Future +def _get_loop(fut): + # Tries to call Future.get_loop() if it's available. + # Otherwise fallbacks to using the old '_loop' property. + try: + get_loop = fut.get_loop + except AttributeError: + pass + else: + return get_loop() + return fut._loop + + def _set_result_unless_cancelled(fut, result): """Helper setting the result only if the future was not cancelled.""" if fut.cancelled(): @@ -304,8 +320,8 @@ def _chain_future(source, destination): if not isfuture(destination) and not isinstance(destination, concurrent.futures.Future): raise TypeError('A future is required for destination argument') - source_loop = source._loop if isfuture(source) else None - dest_loop = destination._loop if isfuture(destination) else None + source_loop = _get_loop(source) if isfuture(source) else None + dest_loop = _get_loop(destination) if isfuture(destination) else None def _set_state(future, other): if isfuture(future): diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index ff8a486b544..572e7073338 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -34,7 +34,7 @@ def all_tasks(loop=None): """Return a set of all tasks for the loop.""" if loop is None: loop = events.get_event_loop() - return {t for t, l in _all_tasks.items() if l is loop} + return {t for t in _all_tasks if futures._get_loop(t) is loop} class Task(futures.Future): @@ -96,7 +96,7 @@ def __init__(self, coro, *, loop=None): self._coro = coro self._loop.call_soon(self._step) - _register_task(self._loop, self) + _register_task(self) def __del__(self): if self._state == futures._PENDING and self._log_destroy_pending: @@ -215,7 +215,7 @@ def _step(self, exc=None): blocking = getattr(result, '_asyncio_future_blocking', None) if blocking is not None: # Yielded Future must come from Future.__iter__(). - if result._loop is not self._loop: + if futures._get_loop(result) is not self._loop: new_exc = RuntimeError( f'Task {self!r} got Future ' f'{result!r} attached to a different loop') @@ -510,9 +510,9 @@ def __sleep0(): if loop is None: loop = events.get_event_loop() future = loop.create_future() - h = future._loop.call_later(delay, - futures._set_result_unless_cancelled, - future, result) + h = loop.call_later(delay, + futures._set_result_unless_cancelled, + future, result) try: return await future finally: @@ -525,7 +525,7 @@ def ensure_future(coro_or_future, *, loop=None): If the argument is a Future, it is returned directly. """ if futures.isfuture(coro_or_future): - if loop is not None and loop is not coro_or_future._loop: + if loop is not None and loop is not futures._get_loop(coro_or_future): raise ValueError('loop argument must agree with Future') return coro_or_future elif coroutines.iscoroutine(coro_or_future): @@ -655,7 +655,7 @@ def _done_callback(fut): if arg not in arg_to_fut: fut = ensure_future(arg, loop=loop) if loop is None: - loop = fut._loop + loop = futures._get_loop(fut) if fut is not arg: # 'arg' was not a Future, therefore, 'fut' is a new # Future created specifically for 'arg'. Since the caller @@ -707,7 +707,7 @@ def shield(arg, *, loop=None): if inner.done(): # Shortcut. return inner - loop = inner._loop + loop = futures._get_loop(inner) outer = loop.create_future() def _done_callback(inner): @@ -751,23 +751,17 @@ def callback(): return future -# WeakKeyDictionary of {Task: EventLoop} containing all tasks alive. -# Task should be a weak reference to remove entry on task garbage -# collection, EventLoop is required -# to not access to private task._loop attribute. -_all_tasks = weakref.WeakKeyDictionary() +# WeakSet containing all alive tasks. +_all_tasks = weakref.WeakSet() # Dictionary containing tasks that are currently active in # all running event loops. {EventLoop: Task} _current_tasks = {} -def _register_task(loop, task): - """Register a new task in asyncio as executed by loop. - - Returns None. - """ - _all_tasks[task] = loop +def _register_task(task): + """Register a new task in asyncio as executed by loop.""" + _all_tasks.add(task) def _enter_task(loop, task): @@ -786,8 +780,9 @@ def _leave_task(loop, task): del _current_tasks[loop] -def _unregister_task(loop, task): - _all_tasks.pop(task, None) +def _unregister_task(task): + """Unregister a task.""" + _all_tasks.discard(task) _py_register_task = _register_task diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 5652a42690e..f777a420b29 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -139,6 +139,7 @@ def test_init_constructor_default_loop(self): asyncio.set_event_loop(self.loop) f = self._new_future() self.assertIs(f._loop, self.loop) + self.assertIs(f.get_loop(), self.loop) def test_constructor_positional(self): # Make sure Future doesn't accept a positional argument diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index f1dbb99d4fc..84669cd6c7e 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -141,6 +141,7 @@ def notmuch(): self.assertTrue(t.done()) self.assertEqual(t.result(), 'ok') self.assertIs(t._loop, self.loop) + self.assertIs(t.get_loop(), self.loop) loop = asyncio.new_event_loop() self.set_event_loop(loop) @@ -2310,10 +2311,11 @@ class BaseTaskIntrospectionTests: def test__register_task(self): task = mock.Mock() loop = mock.Mock() + task.get_loop = lambda: loop self.assertEqual(asyncio.all_tasks(loop), set()) - self._register_task(loop, task) + self._register_task(task) self.assertEqual(asyncio.all_tasks(loop), {task}) - self._unregister_task(loop, task) + self._unregister_task(task) def test__enter_task(self): task = mock.Mock() @@ -2360,14 +2362,15 @@ def test__leave_task_failure2(self): def test__unregister_task(self): task = mock.Mock() loop = mock.Mock() - self._register_task(loop, task) - self._unregister_task(loop, task) + task.get_loop = lambda: loop + self._register_task(task) + self._unregister_task(task) self.assertEqual(asyncio.all_tasks(loop), set()) def test__unregister_task_not_registered(self): task = mock.Mock() loop = mock.Mock() - self._unregister_task(loop, task) + self._unregister_task(task) self.assertEqual(asyncio.all_tasks(loop), set()) diff --git a/Misc/NEWS.d/next/Library/2017-12-23-12-45-00.bpo-32415.YufXTU.rst b/Misc/NEWS.d/next/Library/2017-12-23-12-45-00.bpo-32415.YufXTU.rst new file mode 100644 index 00000000000..f1f57376241 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-23-12-45-00.bpo-32415.YufXTU.rst @@ -0,0 +1 @@ +asyncio: Add Task.get_loop() and Future.get_loop() diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index f52297d33f2..25acd552b18 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -16,7 +16,6 @@ _Py_IDENTIFIER(call_soon); _Py_IDENTIFIER(cancel); _Py_IDENTIFIER(current_task); _Py_IDENTIFIER(get_event_loop); -_Py_IDENTIFIER(pop); _Py_IDENTIFIER(send); _Py_IDENTIFIER(throw); _Py_IDENTIFIER(_step); @@ -39,15 +38,12 @@ static PyObject *asyncio_InvalidStateError; static PyObject *asyncio_CancelledError; -/* WeakKeyDictionary of {Task: EventLoop} containing all tasks alive. - Task should be a weak reference to remove entry on task garbage - collection, EventLoop is required - to not access to private task._loop attribute. */ -static PyObject *current_tasks; +/* WeakSet containing all alive tasks. */ +static PyObject *all_tasks; /* Dictionary containing tasks that are currently active in all running event loops. {EventLoop: Task} */ -static PyObject *all_tasks; +static PyObject *current_tasks; /* An isinstance type cache for the 'is_coroutine()' function. */ static PyObject *iscoroutine_typecache; @@ -186,6 +182,31 @@ is_coroutine(PyObject *coro) } +static PyObject * +get_future_loop(PyObject *fut) +{ + /* Implementation of `asyncio.futures._get_loop` */ + + _Py_IDENTIFIER(get_loop); + _Py_IDENTIFIER(_loop); + + if (Future_CheckExact(fut) || Task_CheckExact(fut)) { + PyObject *loop = ((FutureObj *)fut)->fut_loop; + Py_INCREF(loop); + return loop; + } + + PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop); + if (getloop != NULL) { + PyObject *res = _PyObject_CallNoArg(getloop); + Py_DECREF(getloop); + return res; + } + + return _PyObject_GetAttrId(fut, &PyId__loop); +} + + static int get_running_loop(PyObject **loop) { @@ -977,6 +998,20 @@ _asyncio_Future_done_impl(FutureObj *self) } } +/*[clinic input] +_asyncio.Future.get_loop + +Return the event loop the Future is bound to. +[clinic start generated code]*/ + +static PyObject * +_asyncio_Future_get_loop_impl(FutureObj *self) +/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/ +{ + Py_INCREF(self->fut_loop); + return self->fut_loop; +} + static PyObject * FutureObj_get_blocking(FutureObj *fut) { @@ -1295,6 +1330,7 @@ static PyMethodDef FutureType_methods[] = { _ASYNCIO_FUTURE_CANCEL_METHODDEF _ASYNCIO_FUTURE_CANCELLED_METHODDEF _ASYNCIO_FUTURE_DONE_METHODDEF + _ASYNCIO_FUTURE_GET_LOOP_METHODDEF _ASYNCIO_FUTURE__REPR_INFO_METHODDEF _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF {NULL, NULL} /* Sentinel */ @@ -1759,19 +1795,27 @@ TaskWakeupMethWrapper_new(TaskObj *task) /* ----- Task introspection helpers */ static int -register_task(PyObject *loop, PyObject *task) +register_task(PyObject *task) { - return PyObject_SetItem(all_tasks, task, loop); + _Py_IDENTIFIER(add); + + PyObject *res = _PyObject_CallMethodIdObjArgs( + all_tasks, &PyId_add, task, NULL); + if (res == NULL) { + return -1; + } + Py_DECREF(res); + return 0; } static int -unregister_task(PyObject *loop, PyObject *task) +unregister_task(PyObject *task) { - PyObject *res; + _Py_IDENTIFIER(discard); - res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_pop, - task, Py_None, NULL); + PyObject *res = _PyObject_CallMethodIdObjArgs( + all_tasks, &PyId_discard, task, NULL); if (res == NULL) { return -1; } @@ -1871,7 +1915,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) if (task_call_step_soon(self, NULL)) { return -1; } - return register_task(self->task_loop, (PyObject*)self); + return register_task((PyObject*)self); } static int @@ -2622,7 +2666,7 @@ task_step_impl(TaskObj *task, PyObject *exc) } /* Check if `result` future is attached to a different loop */ - PyObject *oloop = PyObject_GetAttrString(result, "_loop"); + PyObject *oloop = get_future_loop(result); if (oloop == NULL) { goto fail; } @@ -2928,7 +2972,6 @@ _asyncio_get_running_loop_impl(PyObject *module) /*[clinic input] _asyncio._register_task - loop: object task: object Register a new task in asyncio as executed by loop. @@ -2937,11 +2980,10 @@ Returns None. [clinic start generated code]*/ static PyObject * -_asyncio__register_task_impl(PyObject *module, PyObject *loop, - PyObject *task) -/*[clinic end generated code: output=54c5cb733dbe0f38 input=9b5fee38fcb2c288]*/ +_asyncio__register_task_impl(PyObject *module, PyObject *task) +/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/ { - if (register_task(loop, task) < 0) { + if (register_task(task) < 0) { return NULL; } Py_RETURN_NONE; @@ -2951,7 +2993,6 @@ _asyncio__register_task_impl(PyObject *module, PyObject *loop, /*[clinic input] _asyncio._unregister_task - loop: object task: object Unregister a task. @@ -2960,11 +3001,10 @@ Returns None. [clinic start generated code]*/ static PyObject * -_asyncio__unregister_task_impl(PyObject *module, PyObject *loop, - PyObject *task) -/*[clinic end generated code: output=f634743a76b84ebc input=51fa1820634ef331]*/ +_asyncio__unregister_task_impl(PyObject *module, PyObject *task) +/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/ { - if (unregister_task(loop, task) < 0) { + if (unregister_task(task) < 0) { return NULL; } Py_RETURN_NONE; @@ -3123,11 +3163,11 @@ module_init(void) WITH_MOD("traceback") GET_MOD_ATTR(traceback_extract_stack, "extract_stack") - PyObject *weak_key_dict; + PyObject *weak_set; WITH_MOD("weakref") - GET_MOD_ATTR(weak_key_dict, "WeakKeyDictionary"); - all_tasks = _PyObject_CallNoArg(weak_key_dict); - Py_CLEAR(weak_key_dict); + GET_MOD_ATTR(weak_set, "WeakSet"); + all_tasks = _PyObject_CallNoArg(weak_set); + Py_CLEAR(weak_set); if (all_tasks == NULL) { goto fail; } diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h index 9d5dea52c8e..6a35434ce3b 100644 --- a/Modules/clinic/_asynciomodule.c.h +++ b/Modules/clinic/_asynciomodule.c.h @@ -194,6 +194,24 @@ _asyncio_Future_done(FutureObj *self, PyObject *Py_UNUSED(ignored)) return _asyncio_Future_done_impl(self); } +PyDoc_STRVAR(_asyncio_Future_get_loop__doc__, +"get_loop($self, /)\n" +"--\n" +"\n" +"Return the event loop the Future is bound to."); + +#define _ASYNCIO_FUTURE_GET_LOOP_METHODDEF \ + {"get_loop", (PyCFunction)_asyncio_Future_get_loop, METH_NOARGS, _asyncio_Future_get_loop__doc__}, + +static PyObject * +_asyncio_Future_get_loop_impl(FutureObj *self); + +static PyObject * +_asyncio_Future_get_loop(FutureObj *self, PyObject *Py_UNUSED(ignored)) +{ + return _asyncio_Future_get_loop_impl(self); +} + PyDoc_STRVAR(_asyncio_Future__repr_info__doc__, "_repr_info($self, /)\n" "--\n" @@ -597,7 +615,7 @@ _asyncio_get_running_loop(PyObject *module, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(_asyncio__register_task__doc__, -"_register_task($module, /, loop, task)\n" +"_register_task($module, /, task)\n" "--\n" "\n" "Register a new task in asyncio as executed by loop.\n" @@ -608,30 +626,28 @@ PyDoc_STRVAR(_asyncio__register_task__doc__, {"_register_task", (PyCFunction)_asyncio__register_task, METH_FASTCALL|METH_KEYWORDS, _asyncio__register_task__doc__}, static PyObject * -_asyncio__register_task_impl(PyObject *module, PyObject *loop, - PyObject *task); +_asyncio__register_task_impl(PyObject *module, PyObject *task); static PyObject * _asyncio__register_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"loop", "task", NULL}; - static _PyArg_Parser _parser = {"OO:_register_task", _keywords, 0}; - PyObject *loop; + static const char * const _keywords[] = {"task", NULL}; + static _PyArg_Parser _parser = {"O:_register_task", _keywords, 0}; PyObject *task; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &loop, &task)) { + &task)) { goto exit; } - return_value = _asyncio__register_task_impl(module, loop, task); + return_value = _asyncio__register_task_impl(module, task); exit: return return_value; } PyDoc_STRVAR(_asyncio__unregister_task__doc__, -"_unregister_task($module, /, loop, task)\n" +"_unregister_task($module, /, task)\n" "--\n" "\n" "Unregister a task.\n" @@ -642,23 +658,21 @@ PyDoc_STRVAR(_asyncio__unregister_task__doc__, {"_unregister_task", (PyCFunction)_asyncio__unregister_task, METH_FASTCALL|METH_KEYWORDS, _asyncio__unregister_task__doc__}, static PyObject * -_asyncio__unregister_task_impl(PyObject *module, PyObject *loop, - PyObject *task); +_asyncio__unregister_task_impl(PyObject *module, PyObject *task); static PyObject * _asyncio__unregister_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"loop", "task", NULL}; - static _PyArg_Parser _parser = {"OO:_unregister_task", _keywords, 0}; - PyObject *loop; + static const char * const _keywords[] = {"task", NULL}; + static _PyArg_Parser _parser = {"O:_unregister_task", _keywords, 0}; PyObject *task; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &loop, &task)) { + &task)) { goto exit; } - return_value = _asyncio__unregister_task_impl(module, loop, task); + return_value = _asyncio__unregister_task_impl(module, task); exit: return return_value; @@ -733,4 +747,4 @@ _asyncio__leave_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=0033af17965b51b4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5d100b3d74f2a0f4 input=a9049054013a1b77]*/ From webhook-mailer at python.org Sat Dec 23 15:06:49 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 23 Dec 2017 20:06:49 -0000 Subject: [Python-checkins] bpo-32357: Use PySet_GET_SIZE macro in _is_coroutine() from _asynciomodule.c (#4990) Message-ID: https://github.com/python/cpython/commit/0f47fa2c89a6b9a04969219dfb0c3801c611e3ca commit: 0f47fa2c89a6b9a04969219dfb0c3801c611e3ca branch: master author: Andrew Svetlov committer: Yury Selivanov date: 2017-12-23T15:06:46-05:00 summary: bpo-32357: Use PySet_GET_SIZE macro in _is_coroutine() from _asynciomodule.c (#4990) files: M Modules/_asynciomodule.c diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 25acd552b18..d626127699a 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -138,7 +138,7 @@ _is_coroutine(PyObject *coro) return is_res_true; } - if (PySet_Size(iscoroutine_typecache) < 100) { + if (PySet_GET_SIZE(iscoroutine_typecache) < 100) { /* Just in case we don't want to cache more than 100 positive types. That shouldn't ever happen, unless someone stressing the system on purpose. From webhook-mailer at python.org Sat Dec 23 15:42:30 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 23 Dec 2017 20:42:30 -0000 Subject: [Python-checkins] bpo-32415: Add more tests (#4995) Message-ID: https://github.com/python/cpython/commit/a8fb07978953d3f55cfce836e3669d8b8e82b4c1 commit: a8fb07978953d3f55cfce836e3669d8b8e82b4c1 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-23T15:42:27-05:00 summary: bpo-32415: Add more tests (#4995) files: M Lib/test/test_asyncio/test_tasks.py diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 84669cd6c7e..7bb43058c80 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2308,10 +2308,28 @@ class BaseTaskIntrospectionTests: _enter_task = None _leave_task = None - def test__register_task(self): - task = mock.Mock() + def test__register_task_1(self): + class TaskLike: + @property + def _loop(self): + return loop + + task = TaskLike() loop = mock.Mock() - task.get_loop = lambda: loop + + self.assertEqual(asyncio.all_tasks(loop), set()) + self._register_task(task) + self.assertEqual(asyncio.all_tasks(loop), {task}) + self._unregister_task(task) + + def test__register_task_2(self): + class TaskLike: + def get_loop(self): + return loop + + task = TaskLike() + loop = mock.Mock() + self.assertEqual(asyncio.all_tasks(loop), set()) self._register_task(task) self.assertEqual(asyncio.all_tasks(loop), {task}) From webhook-mailer at python.org Sat Dec 23 16:03:30 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 23 Dec 2017 21:03:30 -0000 Subject: [Python-checkins] Fix check for run_in_executor on closed loop. (#4996) Message-ID: https://github.com/python/cpython/commit/a330f483e2d05f3ad1780f0542ecd8d2b0dda5df commit: a330f483e2d05f3ad1780f0542ecd8d2b0dda5df branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-23T23:03:27+02:00 summary: Fix check for run_in_executor on closed loop. (#4996) files: M Lib/test/test_asyncio/test_events.py diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index e5e41fc1a87..79e8d79e6b1 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1842,14 +1842,18 @@ def test(): self.loop.call_later(1.0, func) with self.assertRaises(RuntimeError): self.loop.call_at(self.loop.time() + .0, func) - with self.assertRaises(RuntimeError): - self.loop.run_until_complete( - self.loop.run_in_executor(None, func)) with self.assertRaises(RuntimeError): self.loop.create_task(coro) with self.assertRaises(RuntimeError): self.loop.add_signal_handler(signal.SIGTERM, func) + # run_in_executor test is tricky: the method is a coroutine, + # but run_until_complete cannot be called on closed loop. + # Thus iterate once explicitly. + with self.assertRaises(RuntimeError): + it = self.loop.run_in_executor(None, func).__await__() + next(it) + class SubprocessTestsMixin: From webhook-mailer at python.org Sat Dec 23 16:29:29 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 23 Dec 2017 21:29:29 -0000 Subject: [Python-checkins] bpo-32415: Fix "error is already set" (#4999) Message-ID: https://github.com/python/cpython/commit/719ccbca69b21013a783b829de3404b5aa243827 commit: 719ccbca69b21013a783b829de3404b5aa243827 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-23T16:29:26-05:00 summary: bpo-32415: Fix "error is already set" (#4999) files: M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 7bb43058c80..4cf694fe7e9 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2302,6 +2302,32 @@ class Future(futures._PyFuture): pass + at unittest.skipUnless(hasattr(tasks, '_CTask'), + 'requires the C _asyncio module') +class CTask_Future_Tests(test_utils.TestCase): + + def test_foobar(self): + class Fut(asyncio.Future): + @property + def get_loop(self): + raise AttributeError + + async def coro(): + await fut + return 'spam' + + self.loop = asyncio.new_event_loop() + try: + fut = Fut(loop=self.loop) + self.loop.call_later(0.1, fut.set_result(1)) + task = asyncio.Task(coro(), loop=self.loop) + res = self.loop.run_until_complete(task) + finally: + self.loop.close() + + self.assertEqual(res, 'spam') + + class BaseTaskIntrospectionTests: _register_task = None _unregister_task = None diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index d626127699a..f70e3457c37 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -203,6 +203,7 @@ get_future_loop(PyObject *fut) return res; } + PyErr_Clear(); return _PyObject_GetAttrId(fut, &PyId__loop); } From webhook-mailer at python.org Sat Dec 23 20:29:23 2017 From: webhook-mailer at python.org (INADA Naoki) Date: Sun, 24 Dec 2017 01:29:23 -0000 Subject: [Python-checkins] bpo-32402: io: Add missing NULL check. (GH-4971) Message-ID: https://github.com/python/cpython/commit/4856b0f34a6f4074cd86e66f11a635422374ae98 commit: 4856b0f34a6f4074cd86e66f11a635422374ae98 branch: master author: INADA Naoki committer: GitHub date: 2017-12-24T10:29:19+09:00 summary: bpo-32402: io: Add missing NULL check. (GH-4971) _PyUnicode_FromId() may return NULL. Reported by coverity scan: CID 1426868, 1426867. files: M Modules/_io/textio.c diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 6800d2dd253..d776b5de699 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1037,6 +1037,9 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, if (errors == Py_None) { errors = _PyUnicode_FromId(&PyId_strict); /* borrowed */ + if (errors == NULL) { + return -1; + } } else if (!PyUnicode_Check(errors)) { // Check 'errors' argument here because Argument Clinic doesn't support @@ -1249,6 +1252,9 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding, } else if (errors == Py_None) { errors = _PyUnicode_FromId(&PyId_strict); + if (errors == NULL) { + return -1; + } } const char *c_errors = PyUnicode_AsUTF8(errors); From solipsis at pitrou.net Sun Dec 24 04:08:03 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 24 Dec 2017 09:08:03 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171224090803.26562.F393B9FCC7D203FC@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 1] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [1, 0, -2] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogSGYxec', '--timeout', '7200'] From webhook-mailer at python.org Sun Dec 24 06:50:07 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sun, 24 Dec 2017 11:50:07 -0000 Subject: [Python-checkins] bpo-26133: Clear signals list on interpreter finalizing (#5002) Message-ID: https://github.com/python/cpython/commit/4f146f9ed133b9ad56d4ee7a653396836af34067 commit: 4f146f9ed133b9ad56d4ee7a653396836af34067 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-24T13:50:03+02:00 summary: bpo-26133: Clear signals list on interpreter finalizing (#5002) files: M Lib/asyncio/unix_events.py diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index ec767f57d3a..5d6a3c09ac7 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -55,10 +55,13 @@ def close(self): for sig in list(self._signal_handlers): self.remove_signal_handler(sig) else: - warinigs.warn(f"Closing the loop {self!r} on interpreter shutdown " - f"stage, signal unsubsription is disabled", - ResourceWarning, - source=self) + if self._signal_handlers: + warinigs.warn(f"Closing the loop {self!r} " + f"on interpreter shutdown " + f"stage, signal unsubsription is disabled", + ResourceWarning, + source=self) + self._signal_handlers.clear() def _process_self_data(self, data): for signum in data: From webhook-mailer at python.org Sun Dec 24 07:31:01 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sun, 24 Dec 2017 12:31:01 -0000 Subject: [Python-checkins] bpo-26133: Clear signals list on interpreter finalizing (GH-5002) (#5003) Message-ID: https://github.com/python/cpython/commit/5ff5d1167de88eb37265dcaf1396d12617a0ace7 commit: 5ff5d1167de88eb37265dcaf1396d12617a0ace7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-24T14:30:57+02:00 summary: bpo-26133: Clear signals list on interpreter finalizing (GH-5002) (#5003) (cherry picked from commit 4f146f9ed133b9ad56d4ee7a653396836af34067) files: M Lib/asyncio/unix_events.py diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index dde1d3588f2..70b7050d9b7 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -65,10 +65,13 @@ def close(self): for sig in list(self._signal_handlers): self.remove_signal_handler(sig) else: - warinigs.warn(f"Closing the loop {self!r} on interpreter shutdown " - f"stage, signal unsubsription is disabled", - ResourceWarning, - source=self) + if self._signal_handlers: + warinigs.warn(f"Closing the loop {self!r} " + f"on interpreter shutdown " + f"stage, signal unsubsription is disabled", + ResourceWarning, + source=self) + self._signal_handlers.clear() def _process_self_data(self, data): for signum in data: From webhook-mailer at python.org Sun Dec 24 19:08:46 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 25 Dec 2017 00:08:46 -0000 Subject: [Python-checkins] bpo-29084: Exclude C API for OrderedDict from the limited C API. (#4900) Message-ID: https://github.com/python/cpython/commit/1b3029ac8370ac76fa9571aef540e10aed0667ff commit: 1b3029ac8370ac76fa9571aef540e10aed0667ff branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-25T02:08:42+02:00 summary: bpo-29084: Exclude C API for OrderedDict from the limited C API. (#4900) files: A Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst M Include/odictobject.h diff --git a/Include/odictobject.h b/Include/odictobject.h index ff6ad64b8b4..8378dc4bfa4 100644 --- a/Include/odictobject.h +++ b/Include/odictobject.h @@ -6,6 +6,7 @@ extern "C" { /* OrderedDict */ +/* This API is optional and mostly redundant. */ #ifndef Py_LIMITED_API @@ -21,10 +22,6 @@ PyAPI_DATA(PyTypeObject) PyODictValues_Type; #define PyODict_CheckExact(op) (Py_TYPE(op) == &PyODict_Type) #define PyODict_SIZE(op) PyDict_GET_SIZE((op)) -#endif /* Py_LIMITED_API */ - -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 - 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); diff --git a/Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst b/Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst new file mode 100644 index 00000000000..940f7160772 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst @@ -0,0 +1,2 @@ +Undocumented C API for OrderedDict has been excluded from the limited C API. +It was added by mistake and actually never worked in the limited C API. From webhook-mailer at python.org Mon Dec 25 02:40:30 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 25 Dec 2017 07:40:30 -0000 Subject: [Python-checkins] bpo-29084: Exclude C API for OrderedDict from the limited C API. (GH-4900) (#5007) Message-ID: https://github.com/python/cpython/commit/d62b7412c18bd5dfa6d7346abfaf8a922818e6db commit: d62b7412c18bd5dfa6d7346abfaf8a922818e6db branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2017-12-25T09:40:27+02:00 summary: bpo-29084: Exclude C API for OrderedDict from the limited C API. (GH-4900) (#5007) (cherry picked from commit 1b3029ac8370ac76fa9571aef540e10aed0667ff) files: A Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst M Include/odictobject.h diff --git a/Include/odictobject.h b/Include/odictobject.h index 381de58ba4c..692194daee8 100644 --- a/Include/odictobject.h +++ b/Include/odictobject.h @@ -6,6 +6,7 @@ extern "C" { /* OrderedDict */ +/* This API is optional and mostly redundant. */ #ifndef Py_LIMITED_API @@ -21,10 +22,6 @@ PyAPI_DATA(PyTypeObject) PyODictValues_Type; #define PyODict_CheckExact(op) (Py_TYPE(op) == &PyODict_Type) #define PyODict_SIZE(op) ((PyDictObject *)op)->ma_used -#endif /* Py_LIMITED_API */ - -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 - 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); diff --git a/Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst b/Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst new file mode 100644 index 00000000000..940f7160772 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2017-12-16-09-59-35.bpo-29084.ZGJ-LJ.rst @@ -0,0 +1,2 @@ +Undocumented C API for OrderedDict has been excluded from the limited C API. +It was added by mistake and actually never worked in the limited C API. From solipsis at pitrou.net Mon Dec 25 04:12:32 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 25 Dec 2017 09:12:32 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=9 Message-ID: <20171225091232.26182.F3DE0E7901ECDF43@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 0, 7] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [-2, 1, -1] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogMsP6Zq', '--timeout', '7200'] From webhook-mailer at python.org Mon Dec 25 05:47:58 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 25 Dec 2017 10:47:58 -0000 Subject: [Python-checkins] bpo-32372: Move __debug__ optimization to the AST level. (#4925) Message-ID: https://github.com/python/cpython/commit/3dfbaf51f0d90646e0414ddbd3b513ee8e5ffe9b commit: 3dfbaf51f0d90646e0414ddbd3b513ee8e5ffe9b branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-25T12:47:50+02:00 summary: bpo-32372: Move __debug__ optimization to the AST level. (#4925) files: M Include/compile.h M Python/ast_opt.c M Python/compile.c diff --git a/Include/compile.h b/Include/compile.h index 2e9accf5edb..edfd8bbfac6 100644 --- a/Include/compile.h +++ b/Include/compile.h @@ -75,7 +75,7 @@ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); #define PY_INVALID_STACK_EFFECT INT_MAX PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg); -PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena); +PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize); #ifdef __cplusplus } diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 2f659d08549..f98a28aa054 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -75,7 +75,7 @@ unary_not(PyObject *v) } static int -fold_unaryop(expr_ty node, PyArena *arena) +fold_unaryop(expr_ty node, PyArena *arena, int optimize) { expr_ty arg = node->v.UnaryOp.operand; @@ -252,7 +252,7 @@ safe_mod(PyObject *v, PyObject *w) } static int -fold_binop(expr_ty node, PyArena *arena) +fold_binop(expr_ty node, PyArena *arena, int optimize) { expr_ty lhs, rhs; lhs = node->v.BinOp.left; @@ -334,7 +334,7 @@ make_const_tuple(asdl_seq *elts) } static int -fold_tuple(expr_ty node, PyArena *arena) +fold_tuple(expr_ty node, PyArena *arena, int optimize) { PyObject *newval; @@ -346,7 +346,7 @@ fold_tuple(expr_ty node, PyArena *arena) } static int -fold_subscr(expr_ty node, PyArena *arena) +fold_subscr(expr_ty node, PyArena *arena, int optimize) { PyObject *newval; expr_ty arg, idx; @@ -374,7 +374,7 @@ fold_subscr(expr_ty node, PyArena *arena) in "for" loop and comprehensions. */ static int -fold_iter(expr_ty arg, PyArena *arena) +fold_iter(expr_ty arg, PyArena *arena, int optimize) { PyObject *newval; if (arg->kind == List_kind) { @@ -393,7 +393,7 @@ fold_iter(expr_ty arg, PyArena *arena) } static int -fold_compare(expr_ty node, PyArena *arena) +fold_compare(expr_ty node, PyArena *arena, int optimize) { asdl_int_seq *ops; asdl_seq *args; @@ -407,29 +407,29 @@ fold_compare(expr_ty node, PyArena *arena) i = asdl_seq_LEN(ops) - 1; int op = asdl_seq_GET(ops, i); if (op == In || op == NotIn) { - if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena)) { + if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) { return 0; } } return 1; } -static int astfold_mod(mod_ty node_, PyArena* ctx_); -static int astfold_stmt(stmt_ty node_, PyArena* ctx_); -static int astfold_expr(expr_ty node_, PyArena* ctx_); -static int astfold_arguments(arguments_ty node_, PyArena* ctx_); -static int astfold_comprehension(comprehension_ty node_, PyArena* ctx_); -static int astfold_keyword(keyword_ty node_, PyArena* ctx_); -static int astfold_slice(slice_ty node_, PyArena* ctx_); -static int astfold_arg(arg_ty node_, PyArena* ctx_); -static int astfold_withitem(withitem_ty node_, PyArena* ctx_); -static int astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_); +static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_); +static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_); +static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_); +static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_); +static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_); +static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_); +static int astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_); +static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_); +static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_); +static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_); #define CALL(FUNC, TYPE, ARG) \ - if (!FUNC((ARG), ctx_)) \ + if (!FUNC((ARG), ctx_, optimize_)) \ return 0; #define CALL_OPT(FUNC, TYPE, ARG) \ - if ((ARG) != NULL && !FUNC((ARG), ctx_)) \ + if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \ return 0; #define CALL_SEQ(FUNC, TYPE, ARG) { \ @@ -437,7 +437,7 @@ static int astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_); asdl_seq *seq = (ARG); /* avoid variable capture */ \ for (i = 0; i < asdl_seq_LEN(seq); i++) { \ TYPE elt = (TYPE)asdl_seq_GET(seq, i); \ - if (elt != NULL && !FUNC(elt, ctx_)) \ + if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \ return 0; \ } \ } @@ -447,13 +447,13 @@ static int astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_); asdl_int_seq *seq = (ARG); /* avoid variable capture */ \ for (i = 0; i < asdl_seq_LEN(seq); i++) { \ TYPE elt = (TYPE)asdl_seq_GET(seq, i); \ - if (!FUNC(elt, ctx_)) \ + if (!FUNC(elt, ctx_, optimize_)) \ return 0; \ } \ } static int -astfold_mod(mod_ty node_, PyArena* ctx_) +astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_) { switch (node_->kind) { case Module_kind: @@ -475,7 +475,7 @@ astfold_mod(mod_ty node_, PyArena* ctx_) } static int -astfold_expr(expr_ty node_, PyArena* ctx_) +astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_) { switch (node_->kind) { case BoolOp_kind: @@ -567,6 +567,11 @@ astfold_expr(expr_ty node_, PyArena* ctx_) CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts); CALL(fold_tuple, expr_ty, node_); break; + case Name_kind: + if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) { + return make_const(node_, PyBool_FromLong(!optimize_), ctx_); + } + break; default: break; } @@ -574,7 +579,7 @@ astfold_expr(expr_ty node_, PyArena* ctx_) } static int -astfold_slice(slice_ty node_, PyArena* ctx_) +astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_) { switch (node_->kind) { case Slice_kind: @@ -595,14 +600,14 @@ astfold_slice(slice_ty node_, PyArena* ctx_) } static int -astfold_keyword(keyword_ty node_, PyArena* ctx_) +astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_) { CALL(astfold_expr, expr_ty, node_->value); return 1; } static int -astfold_comprehension(comprehension_ty node_, PyArena* ctx_) +astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_) { CALL(astfold_expr, expr_ty, node_->target); CALL(astfold_expr, expr_ty, node_->iter); @@ -613,7 +618,7 @@ astfold_comprehension(comprehension_ty node_, PyArena* ctx_) } static int -astfold_arguments(arguments_ty node_, PyArena* ctx_) +astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_) { CALL_SEQ(astfold_arg, arg_ty, node_->args); CALL_OPT(astfold_arg, arg_ty, node_->vararg); @@ -625,14 +630,14 @@ astfold_arguments(arguments_ty node_, PyArena* ctx_) } static int -astfold_arg(arg_ty node_, PyArena* ctx_) +astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_) { CALL_OPT(astfold_expr, expr_ty, node_->annotation); return 1; } static int -astfold_stmt(stmt_ty node_, PyArena* ctx_) +astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_) { switch (node_->kind) { case FunctionDef_kind: @@ -728,7 +733,7 @@ astfold_stmt(stmt_ty node_, PyArena* ctx_) } static int -astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_) +astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_) { switch (node_->kind) { case ExceptHandler_kind: @@ -742,7 +747,7 @@ astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_) } static int -astfold_withitem(withitem_ty node_, PyArena* ctx_) +astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_) { CALL(astfold_expr, expr_ty, node_->context_expr); CALL_OPT(astfold_expr, expr_ty, node_->optional_vars); @@ -755,9 +760,9 @@ astfold_withitem(withitem_ty node_, PyArena* ctx_) #undef CALL_INT_SEQ int -_PyAST_Optimize(mod_ty mod, PyArena *arena) +_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize) { - int ret = astfold_mod(mod, arena); + int ret = astfold_mod(mod, arena, optimize); assert(ret || PyErr_Occurred()); return ret; } diff --git a/Python/compile.c b/Python/compile.c index 392de40f20a..e5745d16e30 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -191,7 +191,7 @@ static void compiler_pop_fblock(struct compiler *, enum fblocktype, static int compiler_in_loop(struct compiler *); static int inplace_binop(struct compiler *, operator_ty); -static int expr_constant(struct compiler *, expr_ty); +static int expr_constant(expr_ty); static int compiler_with(struct compiler *, stmt_ty, int); static int compiler_async_with(struct compiler *, stmt_ty, int); @@ -331,7 +331,7 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize; c.c_nestlevel = 0; - if (!_PyAST_Optimize(mod, arena)) { + if (!_PyAST_Optimize(mod, arena, c.c_optimize)) { goto finally; } @@ -1332,15 +1332,13 @@ is_const(expr_ty e) case Ellipsis_kind: case NameConstant_kind: return 1; - case Name_kind: - return _PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__"); default: return 0; } } static PyObject * -get_const_value(struct compiler *c, expr_ty e) +get_const_value(expr_ty e) { switch (e->kind) { case Constant_kind: @@ -1355,9 +1353,6 @@ get_const_value(struct compiler *c, expr_ty e) return Py_Ellipsis; case NameConstant_kind: return e->v.NameConstant.value; - case Name_kind: - assert(_PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__")); - return c->c_optimize ? Py_False : Py_True; default: Py_UNREACHABLE(); } @@ -2217,7 +2212,7 @@ compiler_if(struct compiler *c, stmt_ty s) if (end == NULL) return 0; - constant = expr_constant(c, s->v.If.test); + constant = expr_constant(s->v.If.test); /* constant = 0: "if 0" * constant = 1: "if 1", "if 2", ... * constant = -1: rest */ @@ -2363,7 +2358,7 @@ static int compiler_while(struct compiler *c, stmt_ty s) { basicblock *loop, *orelse, *end, *anchor = NULL; - int constant = expr_constant(c, s->v.While.test); + int constant = expr_constant(s->v.While.test); if (constant == 0) { if (s->v.While.orelse) @@ -3098,11 +3093,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) !_PyUnicode_EqualToASCIIString(name, "True") && !_PyUnicode_EqualToASCIIString(name, "False")); - if (ctx == Load && _PyUnicode_EqualToASCIIString(name, "__debug__")) { - ADDOP_O(c, LOAD_CONST, c->c_optimize ? Py_False : Py_True, consts); - return 1; - } - mangled = _Py_Mangle(c->u->u_private, name); if (!mangled) return 0; @@ -3370,7 +3360,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end return 0; } for (i = begin; i < end; i++) { - key = get_const_value(c, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); Py_INCREF(key); PyTuple_SET_ITEM(keys, i - begin, key); } @@ -4140,10 +4130,10 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) */ static int -expr_constant(struct compiler *c, expr_ty e) +expr_constant(expr_ty e) { if (is_const(e)) { - return PyObject_IsTrue(get_const_value(c, e)); + return PyObject_IsTrue(get_const_value(e)); } return -1; } From webhook-mailer at python.org Mon Dec 25 10:48:18 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 25 Dec 2017 15:48:18 -0000 Subject: [Python-checkins] bpo-32363: Disable Task.set_exception() and Task.set_result() (#4923) Message-ID: https://github.com/python/cpython/commit/0cf16f9ea014b17d398ee3971d4976c698533318 commit: 0cf16f9ea014b17d398ee3971d4976c698533318 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-25T10:48:15-05:00 summary: bpo-32363: Disable Task.set_exception() and Task.set_result() (#4923) files: A Misc/NEWS.d/next/Library/2017-12-19-00-37-28.bpo-32363.YTeGU0.rst M Lib/asyncio/futures.py M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c M Modules/clinic/_asynciomodule.c.h diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 24843c016a7..13fb47cdc68 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -239,14 +239,15 @@ def set_exception(self, exception): self._schedule_callbacks() self._log_traceback = True - def __iter__(self): + def __await__(self): if not self.done(): self._asyncio_future_blocking = True yield self # This tells Task to wait for completion. - assert self.done(), "await wasn't used with future" + if not self.done(): + raise RuntimeError("await wasn't used with future") return self.result() # May raise too. - __await__ = __iter__ # make compatible with 'await' expression + __iter__ = __await__ # make compatible with 'yield from'. # Needed for testing purposes. diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 572e7073338..b11808853e2 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -37,7 +37,9 @@ def all_tasks(loop=None): return {t for t in _all_tasks if futures._get_loop(t) is loop} -class Task(futures.Future): +class Task(futures._PyFuture): # Inherit Python Task implementation + # from a Python Future implementation. + """A coroutine wrapped in a Future.""" # An important invariant maintained while a Task not done: @@ -107,11 +109,17 @@ def __del__(self): if self._source_traceback: context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) - futures.Future.__del__(self) + super().__del__() def _repr_info(self): return base_tasks._task_repr_info(self) + def set_result(self, result): + raise RuntimeError('Task does not support set_result operation') + + def set_exception(self, exception): + raise RuntimeError('Task does not support set_exception operation') + def get_stack(self, *, limit=None): """Return the list of stack frames for this task's coroutine. @@ -180,7 +188,9 @@ def cancel(self): return True def _step(self, exc=None): - assert not self.done(), f'_step(): already done: {self!r}, {exc!r}' + if self.done(): + raise futures.InvalidStateError( + f'_step(): already done: {self!r}, {exc!r}') if self._must_cancel: if not isinstance(exc, futures.CancelledError): exc = futures.CancelledError() @@ -201,15 +211,15 @@ def _step(self, exc=None): if self._must_cancel: # Task is cancelled right before coro stops. self._must_cancel = False - self.set_exception(futures.CancelledError()) + super().set_exception(futures.CancelledError()) else: - self.set_result(exc.value) + super().set_result(exc.value) except futures.CancelledError: super().cancel() # I.e., Future.cancel(self). except Exception as exc: - self.set_exception(exc) + super().set_exception(exc) except BaseException as exc: - self.set_exception(exc) + super().set_exception(exc) raise else: blocking = getattr(result, '_asyncio_future_blocking', None) diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index f777a420b29..d3396162ba6 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -370,7 +370,8 @@ def coro(): def test(): arg1, arg2 = coro() - self.assertRaises(AssertionError, test) + with self.assertRaisesRegex(RuntimeError, "await wasn't used"): + test() fut.cancel() @mock.patch('asyncio.base_events.logger') diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 4cf694fe7e9..0dc6c32fde4 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1332,17 +1332,23 @@ def coro(): self.assertIsNone(task._fut_waiter) self.assertTrue(fut.cancelled()) - def test_step_in_completed_task(self): + def test_task_set_methods(self): @asyncio.coroutine def notmuch(): return 'ko' gen = notmuch() task = self.new_task(self.loop, gen) - task.set_result('ok') - self.assertRaises(AssertionError, task._step) - gen.close() + with self.assertRaisesRegex(RuntimeError, 'not support set_result'): + task.set_result('ok') + + with self.assertRaisesRegex(RuntimeError, 'not support set_exception'): + task.set_exception(ValueError()) + + self.assertEqual( + self.loop.run_until_complete(task), + 'ko') def test_step_result(self): @asyncio.coroutine @@ -2231,10 +2237,59 @@ def test_subclasses_ctask_cfuture(self): return cls +class SetMethodsTest: + + def test_set_result_causes_invalid_state(self): + Future = type(self).Future + self.loop.call_exception_handler = exc_handler = mock.Mock() + + async def foo(): + await asyncio.sleep(0.1, loop=self.loop) + return 10 + + task = self.new_task(self.loop, foo()) + Future.set_result(task, 'spam') + + self.assertEqual( + self.loop.run_until_complete(task), + 'spam') + + exc_handler.assert_called_once() + exc = exc_handler.call_args[0][0]['exception'] + with self.assertRaisesRegex(asyncio.InvalidStateError, + r'step\(\): already done'): + raise exc + + def test_set_exception_causes_invalid_state(self): + class MyExc(Exception): + pass + + Future = type(self).Future + self.loop.call_exception_handler = exc_handler = mock.Mock() + + async def foo(): + await asyncio.sleep(0.1, loop=self.loop) + return 10 + + task = self.new_task(self.loop, foo()) + Future.set_exception(task, MyExc()) + + with self.assertRaises(MyExc): + self.loop.run_until_complete(task) + + exc_handler.assert_called_once() + exc = exc_handler.call_args[0][0]['exception'] + with self.assertRaisesRegex(asyncio.InvalidStateError, + r'step\(\): already done'): + raise exc + + @unittest.skipUnless(hasattr(futures, '_CFuture') and hasattr(tasks, '_CTask'), 'requires the C _asyncio module') -class CTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase): +class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest, + test_utils.TestCase): + Task = getattr(tasks, '_CTask', None) Future = getattr(futures, '_CFuture', None) @@ -2245,11 +2300,8 @@ class CTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase): @add_subclass_tests class CTask_CFuture_SubclassTests(BaseTaskTests, test_utils.TestCase): - class Task(tasks._CTask): - pass - - class Future(futures._CFuture): - pass + Task = getattr(tasks, '_CTask', None) + Future = getattr(futures, '_CFuture', None) @unittest.skipUnless(hasattr(tasks, '_CTask'), @@ -2257,9 +2309,7 @@ class Future(futures._CFuture): @add_subclass_tests class CTaskSubclass_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): - class Task(tasks._CTask): - pass - + Task = getattr(tasks, '_CTask', None) Future = futures._PyFuture @@ -2268,15 +2318,14 @@ class Task(tasks._CTask): @add_subclass_tests class PyTask_CFutureSubclass_Tests(BaseTaskTests, test_utils.TestCase): - class Future(futures._CFuture): - pass - + Future = getattr(futures, '_CFuture', None) Task = tasks._PyTask @unittest.skipUnless(hasattr(tasks, '_CTask'), 'requires the C _asyncio module') class CTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): + Task = getattr(tasks, '_CTask', None) Future = futures._PyFuture @@ -2284,22 +2333,22 @@ class CTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): @unittest.skipUnless(hasattr(futures, '_CFuture'), 'requires the C _asyncio module') class PyTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase): + Task = tasks._PyTask Future = getattr(futures, '_CFuture', None) -class PyTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): +class PyTask_PyFuture_Tests(BaseTaskTests, SetMethodsTest, + test_utils.TestCase): + Task = tasks._PyTask Future = futures._PyFuture @add_subclass_tests class PyTask_PyFuture_SubclassTests(BaseTaskTests, test_utils.TestCase): - class Task(tasks._PyTask): - pass - - class Future(futures._PyFuture): - pass + Task = tasks._PyTask + Future = futures._PyFuture @unittest.skipUnless(hasattr(tasks, '_CTask'), diff --git a/Misc/NEWS.d/next/Library/2017-12-19-00-37-28.bpo-32363.YTeGU0.rst b/Misc/NEWS.d/next/Library/2017-12-19-00-37-28.bpo-32363.YTeGU0.rst new file mode 100644 index 00000000000..4c376c5ea91 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-19-00-37-28.bpo-32363.YTeGU0.rst @@ -0,0 +1,4 @@ +Make asyncio.Task.set_exception() and set_result() raise +NotImplementedError. Task._step() and Future.__await__() raise proper +exceptions when they are in an invalid state, instead of raising an +AssertionError. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index f70e3457c37..f8165abcaa2 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -779,7 +779,7 @@ _asyncio_Future_exception_impl(FutureObj *self) /*[clinic input] _asyncio.Future.set_result - res: object + result: object / Mark the future done and set its result. @@ -789,11 +789,11 @@ InvalidStateError. [clinic start generated code]*/ static PyObject * -_asyncio_Future_set_result(FutureObj *self, PyObject *res) -/*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/ +_asyncio_Future_set_result(FutureObj *self, PyObject *result) +/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/ { ENSURE_FUTURE_ALIVE(self) - return future_set_result(self, res); + return future_set_result(self, result); } /*[clinic input] @@ -1468,8 +1468,8 @@ FutureIter_iternext(futureiterobject *it) Py_INCREF(fut); return (PyObject *)fut; } - PyErr_SetString(PyExc_AssertionError, - "yield from wasn't used with future"); + PyErr_SetString(PyExc_RuntimeError, + "await wasn't used with future"); return NULL; } @@ -2232,6 +2232,39 @@ _asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut) return task_wakeup(self, fut); } +/*[clinic input] +_asyncio.Task.set_result + + result: object + / +[clinic start generated code]*/ + +static PyObject * +_asyncio_Task_set_result(TaskObj *self, PyObject *result) +/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/ +{ + PyErr_SetString(PyExc_RuntimeError, + "Task does not support set_result operation"); + return NULL; +} + +/*[clinic input] +_asyncio.Task.set_exception + + exception: object + / +[clinic start generated code]*/ + +static PyObject * +_asyncio_Task_set_exception(TaskObj *self, PyObject *exception) +/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/ +{ + PyErr_SetString(PyExc_RuntimeError, + "Task doed not support set_exception operation"); + return NULL; +} + + static void TaskObj_finalize(TaskObj *task) { @@ -2304,12 +2337,12 @@ static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */ static PyMethodDef TaskType_methods[] = { _ASYNCIO_FUTURE_RESULT_METHODDEF _ASYNCIO_FUTURE_EXCEPTION_METHODDEF - _ASYNCIO_FUTURE_SET_RESULT_METHODDEF - _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF _ASYNCIO_FUTURE_CANCELLED_METHODDEF _ASYNCIO_FUTURE_DONE_METHODDEF + _ASYNCIO_TASK_SET_RESULT_METHODDEF + _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF _ASYNCIO_TASK_CURRENT_TASK_METHODDEF _ASYNCIO_TASK_ALL_TASKS_METHODDEF _ASYNCIO_TASK_CANCEL_METHODDEF @@ -2461,7 +2494,7 @@ task_step_impl(TaskObj *task, PyObject *exc) PyObject *o; if (task->task_state != STATE_PENDING) { - PyErr_Format(PyExc_AssertionError, + PyErr_Format(asyncio_InvalidStateError, "_step(): already done: %R %R", task, exc ? exc : Py_None); diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h index 6a35434ce3b..f2e0f405ada 100644 --- a/Modules/clinic/_asynciomodule.c.h +++ b/Modules/clinic/_asynciomodule.c.h @@ -86,7 +86,7 @@ _asyncio_Future_exception(FutureObj *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(_asyncio_Future_set_result__doc__, -"set_result($self, res, /)\n" +"set_result($self, result, /)\n" "--\n" "\n" "Mark the future done and set its result.\n" @@ -536,6 +536,22 @@ _asyncio_Task__wakeup(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, Py return return_value; } +PyDoc_STRVAR(_asyncio_Task_set_result__doc__, +"set_result($self, result, /)\n" +"--\n" +"\n"); + +#define _ASYNCIO_TASK_SET_RESULT_METHODDEF \ + {"set_result", (PyCFunction)_asyncio_Task_set_result, METH_O, _asyncio_Task_set_result__doc__}, + +PyDoc_STRVAR(_asyncio_Task_set_exception__doc__, +"set_exception($self, exception, /)\n" +"--\n" +"\n"); + +#define _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF \ + {"set_exception", (PyCFunction)_asyncio_Task_set_exception, METH_O, _asyncio_Task_set_exception__doc__}, + PyDoc_STRVAR(_asyncio__get_running_loop__doc__, "_get_running_loop($module, /)\n" "--\n" @@ -747,4 +763,4 @@ _asyncio__leave_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=5d100b3d74f2a0f4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=616e814431893dcc input=a9049054013a1b77]*/ From webhook-mailer at python.org Mon Dec 25 12:03:27 2017 From: webhook-mailer at python.org (INADA Naoki) Date: Mon, 25 Dec 2017 17:03:27 -0000 Subject: [Python-checkins] bpo-32422: Reduce lru_cache memory usage (GH-5008) Message-ID: https://github.com/python/cpython/commit/3070b71e5eedf62e49b8e7dedab75742a5f67ece commit: 3070b71e5eedf62e49b8e7dedab75742a5f67ece branch: master author: INADA Naoki committer: GitHub date: 2017-12-26T02:03:24+09:00 summary: bpo-32422: Reduce lru_cache memory usage (GH-5008) files: A Misc/NEWS.d/next/Library/2017-12-25-20-22-47.bpo-32422.5H3Wq2.rst M Modules/_functoolsmodule.c diff --git a/Misc/NEWS.d/next/Library/2017-12-25-20-22-47.bpo-32422.5H3Wq2.rst b/Misc/NEWS.d/next/Library/2017-12-25-20-22-47.bpo-32422.5H3Wq2.rst new file mode 100644 index 00000000000..5918c322237 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-25-20-22-47.bpo-32422.5H3Wq2.rst @@ -0,0 +1,2 @@ +``functools.lru_cache`` uses less memory (3 words for each cached key) and +takes about 1/3 time for cyclic GC. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index a571045bcc7..ff4172d663b 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -677,26 +677,9 @@ typedef struct 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; + PyObject_Del(link); } static PyTypeObject lru_list_elem_type = { @@ -720,10 +703,7 @@ static PyTypeObject lru_list_elem_type = { 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 */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ }; @@ -959,8 +939,8 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds } } 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); + link = (lru_list_elem *)PyObject_New(lru_list_elem, + &lru_list_elem_type); if (link == NULL) { Py_DECREF(key); Py_DECREF(result); @@ -970,7 +950,6 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds link->hash = hash; link->key = key; link->result = result; - _PyObject_GC_TRACK(link); if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, hash) < 0) { Py_DECREF(link); @@ -1151,7 +1130,8 @@ 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); + Py_VISIT(link->key); + Py_VISIT(link->result); link = next; } Py_VISIT(self->maxsize_O); From webhook-mailer at python.org Mon Dec 25 16:16:13 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 25 Dec 2017 21:16:13 -0000 Subject: [Python-checkins] bpo-31721: Allow Future._log_traceback to only be set to False (#5009) Message-ID: https://github.com/python/cpython/commit/e0aef4f3cd339a405d2a7fbd35a50afa64834f84 commit: e0aef4f3cd339a405d2a7fbd35a50afa64834f84 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-25T16:16:10-05:00 summary: bpo-31721: Allow Future._log_traceback to only be set to False (#5009) files: A Misc/NEWS.d/next/Library/2017-12-25-11-09-46.bpo-31721.5gM972.rst M Lib/asyncio/futures.py M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 13fb47cdc68..1c05b2231c1 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -65,7 +65,7 @@ class Future: # `yield Future()` (incorrect). _asyncio_future_blocking = False - _log_traceback = False + __log_traceback = False def __init__(self, *, loop=None): """Initialize the future. @@ -90,7 +90,7 @@ def __repr__(self): ' '.join(self._repr_info())) def __del__(self): - if not self._log_traceback: + if not self.__log_traceback: # set_exception() was not called, or result() or exception() # has consumed the exception return @@ -105,6 +105,16 @@ def __del__(self): context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) + @property + def _log_traceback(self): + return self.__log_traceback + + @_log_traceback.setter + def _log_traceback(self, val): + if bool(val): + raise ValueError('_log_traceback can only be set to False') + self.__log_traceback = False + def get_loop(self): """Return the event loop the Future is bound to.""" return self._loop @@ -116,7 +126,7 @@ def cancel(self): change the future's state to cancelled, schedule the callbacks and return True. """ - self._log_traceback = False + self.__log_traceback = False if self._state != _PENDING: return False self._state = _CANCELLED @@ -162,7 +172,7 @@ def result(self): raise CancelledError if self._state != _FINISHED: raise InvalidStateError('Result is not ready.') - self._log_traceback = False + self.__log_traceback = False if self._exception is not None: raise self._exception return self._result @@ -179,7 +189,7 @@ def exception(self): raise CancelledError if self._state != _FINISHED: raise InvalidStateError('Exception is not set.') - self._log_traceback = False + self.__log_traceback = False return self._exception def add_done_callback(self, fn): @@ -237,7 +247,7 @@ def set_exception(self, exception): self._exception = exception self._state = _FINISHED self._schedule_callbacks() - self._log_traceback = True + self.__log_traceback = True def __await__(self): if not self.done(): diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index d3396162ba6..ab45ee39ab9 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -374,6 +374,11 @@ def test(): test() fut.cancel() + def test_log_traceback(self): + fut = self._new_future(loop=self.loop) + with self.assertRaisesRegex(ValueError, 'can only be set to False'): + fut._log_traceback = True + @mock.patch('asyncio.base_events.logger') def test_tb_logger_abandoned(self, m_log): fut = self._new_future(loop=self.loop) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 0dc6c32fde4..26e4f643d1a 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -623,6 +623,15 @@ def gen(): t.cancel() self.assertRaises(asyncio.CancelledError, loop.run_until_complete, t) + def test_log_traceback(self): + async def coro(): + pass + + task = self.new_task(self.loop, coro()) + with self.assertRaisesRegex(ValueError, 'can only be set to False'): + task._log_traceback = True + self.loop.run_until_complete(task) + def test_wait_for_timeout_less_then_0_or_0_future_done(self): def gen(): when = yield diff --git a/Misc/NEWS.d/next/Library/2017-12-25-11-09-46.bpo-31721.5gM972.rst b/Misc/NEWS.d/next/Library/2017-12-25-11-09-46.bpo-31721.5gM972.rst new file mode 100644 index 00000000000..a989a94a7df --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-25-11-09-46.bpo-31721.5gM972.rst @@ -0,0 +1,2 @@ +Prevent Python crash from happening when Future._log_traceback is set to +True manually. Now it can only be set to False, or a ValueError is raised. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index f8165abcaa2..5ec4ad182ab 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1058,6 +1058,11 @@ FutureObj_set_log_traceback(FutureObj *fut, PyObject *val) if (is_true < 0) { return -1; } + if (is_true) { + PyErr_SetString(PyExc_ValueError, + "_log_traceback can only be set to False"); + return -1; + } fut->fut_log_tb = is_true; return 0; } From solipsis at pitrou.net Tue Dec 26 04:15:21 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 26 Dec 2017 09:15:21 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-2 Message-ID: <20171226091521.20969.71D7DBCC3DCEE7B7@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 0] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog1GvrFc', '--timeout', '7200'] From webhook-mailer at python.org Tue Dec 26 04:53:46 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Tue, 26 Dec 2017 09:53:46 -0000 Subject: [Python-checkins] bpo-26133: Fix typos (#5010) Message-ID: https://github.com/python/cpython/commit/a8f4e15f3d33084862ddd3a7d58cd00034e94f16 commit: a8f4e15f3d33084862ddd3a7d58cd00034e94f16 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-26T11:53:38+02:00 summary: bpo-26133: Fix typos (#5010) * Fix typos * Change warning text * Add test files: M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_unix_events.py diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 5d6a3c09ac7..4f6beb43650 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -56,9 +56,9 @@ def close(self): self.remove_signal_handler(sig) else: if self._signal_handlers: - warinigs.warn(f"Closing the loop {self!r} " + warnings.warn(f"Closing the loop {self!r} " f"on interpreter shutdown " - f"stage, signal unsubsription is disabled", + f"stage, skipping signal handlers removal", ResourceWarning, source=self) self._signal_handlers.clear() diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 097d0ef73dc..53ed3d94ddb 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -229,6 +229,23 @@ def test_close(self, m_signal): self.assertEqual(len(self.loop._signal_handlers), 0) m_signal.set_wakeup_fd.assert_called_once_with(-1) + @mock.patch('asyncio.unix_events.sys') + @mock.patch('asyncio.unix_events.signal') + def test_close_on_finalizing(self, m_signal, m_sys): + m_signal.NSIG = signal.NSIG + self.loop.add_signal_handler(signal.SIGHUP, lambda: True) + + self.assertEqual(len(self.loop._signal_handlers), 1) + m_sys.is_finalizing.return_value = True + m_signal.signal.reset_mock() + + with self.assertWarnsRegex(ResourceWarning, + "skipping signal handlers removal"): + self.loop.close() + + self.assertEqual(len(self.loop._signal_handlers), 0) + self.assertFalse(m_signal.signal.called) + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'UNIX Sockets are not supported') From webhook-mailer at python.org Tue Dec 26 05:29:36 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Tue, 26 Dec 2017 10:29:36 -0000 Subject: [Python-checkins] bpo-26133: Fix typos (GH-5010) (#5014) Message-ID: https://github.com/python/cpython/commit/32518b439b9590cce0ef0639e558dc1ce2e152bb commit: 32518b439b9590cce0ef0639e558dc1ce2e152bb branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2017-12-26T12:29:29+02:00 summary: bpo-26133: Fix typos (GH-5010) (#5014) * Fix typos * Change warning text * Add test (cherry picked from commit a8f4e15f3d33084862ddd3a7d58cd00034e94f16) files: M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_unix_events.py diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 70b7050d9b7..b18824fd33b 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -66,9 +66,9 @@ def close(self): self.remove_signal_handler(sig) else: if self._signal_handlers: - warinigs.warn(f"Closing the loop {self!r} " + warnings.warn(f"Closing the loop {self!r} " f"on interpreter shutdown " - f"stage, signal unsubsription is disabled", + f"stage, skipping signal handlers removal", ResourceWarning, source=self) self._signal_handlers.clear() diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 5a499841352..868751bdedc 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -230,6 +230,23 @@ def test_close(self, m_signal): self.assertEqual(len(self.loop._signal_handlers), 0) m_signal.set_wakeup_fd.assert_called_once_with(-1) + @mock.patch('asyncio.unix_events.sys') + @mock.patch('asyncio.unix_events.signal') + def test_close_on_finalizing(self, m_signal, m_sys): + m_signal.NSIG = signal.NSIG + self.loop.add_signal_handler(signal.SIGHUP, lambda: True) + + self.assertEqual(len(self.loop._signal_handlers), 1) + m_sys.is_finalizing.return_value = True + m_signal.signal.reset_mock() + + with self.assertWarnsRegex(ResourceWarning, + "skipping signal handlers removal"): + self.loop.close() + + self.assertEqual(len(self.loop._signal_handlers), 0) + self.assertFalse(m_signal.signal.called) + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'UNIX Sockets are not supported') From webhook-mailer at python.org Tue Dec 26 05:30:43 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 26 Dec 2017 10:30:43 -0000 Subject: [Python-checkins] bpo-32259: Make a TypeError message when unpack non-iterable more specific. (#4903) Message-ID: https://github.com/python/cpython/commit/13a6c098c215921e35004f9d3a9b70f601e56500 commit: 13a6c098c215921e35004f9d3a9b70f601e56500 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-26T12:30:41+02:00 summary: bpo-32259: Make a TypeError message when unpack non-iterable more specific. (#4903) files: A Misc/NEWS.d/next/Core and Builtins/2017-12-16-14-30-21.bpo-32259.GoOJiX.rst M Lib/test/test_dataclasses.py M Lib/test/test_unpack.py M Lib/test/test_unpack_ex.py M Python/ceval.c diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 18ca202ca74..7fbea76ccd8 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -866,7 +866,7 @@ class Date: self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3)) # Make sure we can't unpack - with self.assertRaisesRegex(TypeError, 'is not iterable'): + with self.assertRaisesRegex(TypeError, 'unpack'): x, y, z = Point3D(4, 5, 6) # Maka sure another class with the same field names isn't diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py index 3fcb18fb43a..1c0c523d685 100644 --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -55,7 +55,7 @@ >>> a, b, c = 7 Traceback (most recent call last): ... - TypeError: 'int' object is not iterable + TypeError: cannot unpack non-iterable int object Unpacking tuple of wrong size @@ -129,7 +129,7 @@ >>> () = 42 Traceback (most recent call last): ... - TypeError: 'int' object is not iterable + TypeError: cannot unpack non-iterable int object Unpacking to an empty iterable should raise ValueError diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py index 6be8f551fcc..45cf051f1ec 100644 --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -263,7 +263,7 @@ >>> a, *b = 7 Traceback (most recent call last): ... - TypeError: 'int' object is not iterable + TypeError: cannot unpack non-iterable int object Unpacking sequence too short diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-16-14-30-21.bpo-32259.GoOJiX.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-16-14-30-21.bpo-32259.GoOJiX.rst new file mode 100644 index 00000000000..1129c759f9f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-16-14-30-21.bpo-32259.GoOJiX.rst @@ -0,0 +1,2 @@ +The error message of a TypeError raised when unpack non-iterable is now more +specific. diff --git a/Python/ceval.c b/Python/ceval.c index 287f1df26b5..9276755f0d1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4137,8 +4137,16 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp) assert(v != NULL); it = PyObject_GetIter(v); - if (it == NULL) - goto Error; + if (it == NULL) { + if (PyErr_ExceptionMatches(PyExc_TypeError) && + v->ob_type->tp_iter == NULL && !PySequence_Check(v)) + { + PyErr_Format(PyExc_TypeError, + "cannot unpack non-iterable %.200s object", + v->ob_type->tp_name); + } + return 0; + } for (; i < argcnt; i++) { w = PyIter_Next(it); From webhook-mailer at python.org Tue Dec 26 17:38:59 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 26 Dec 2017 22:38:59 -0000 Subject: [Python-checkins] bpo-32416: Refactor tests for the f_lineno setter and add new tests. (#4991) Message-ID: https://github.com/python/cpython/commit/53f9135667226f33e049e327db60fb033afbd77a commit: 53f9135667226f33e049e327db60fb033afbd77a branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-27T00:38:56+02:00 summary: bpo-32416: Refactor tests for the f_lineno setter and add new tests. (#4991) files: M Lib/test/test_sys_settrace.py diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 51dd9d95b2d..4d88ae5fc2e 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -5,6 +5,19 @@ import sys import difflib import gc +from functools import wraps + +class tracecontext: + """Contex manager that traces its enter and exit.""" + def __init__(self, output, value): + self.output = output + self.value = value + + def __enter__(self): + self.output.append(self.value) + + def __exit__(self, *exc_info): + self.output.append(-self.value) # A very basic example. If this fails, we're in deep trouble. def basic(): @@ -541,14 +554,12 @@ def g(frame, event, arg): # command (aka. "Set next statement"). class JumpTracer: - """Defines a trace function that jumps from one place to another, - with the source and destination lines of the jump being defined by - the 'jump' property of the function under test.""" + """Defines a trace function that jumps from one place to another.""" - def __init__(self, function): + def __init__(self, function, jumpFrom, jumpTo): self.function = function - self.jumpFrom = function.jump[0] - self.jumpTo = function.jump[1] + self.jumpFrom = jumpFrom + self.jumpTo = jumpTo self.done = False def trace(self, frame, event, arg): @@ -564,294 +575,453 @@ def trace(self, frame, event, arg): self.done = True return self.trace -# The first set of 'jump' tests are for things that are allowed: +# This verifies the line-numbers-must-be-integers rule. +def no_jump_to_non_integers(output): + try: + output.append(2) + except ValueError as e: + output.append('integer' in str(e)) -def jump_simple_forwards(output): - output.append(1) - output.append(2) - output.append(3) +# This verifies that you can't set f_lineno via _getframe or similar +# trickery. +def no_jump_without_trace_function(): + try: + previous_frame = sys._getframe().f_back + previous_frame.f_lineno = previous_frame.f_lineno + except ValueError as e: + # This is the exception we wanted; make sure the error message + # talks about trace functions. + if 'trace' not in str(e): + raise + else: + # Something's wrong - the expected exception wasn't raised. + raise AssertionError("Trace-function-less jump failed to fail") -jump_simple_forwards.jump = (1, 3) -jump_simple_forwards.output = [3] -def jump_simple_backwards(output): - output.append(1) - output.append(2) +class JumpTestCase(unittest.TestCase): + def setUp(self): + self.addCleanup(sys.settrace, sys.gettrace()) + sys.settrace(None) -jump_simple_backwards.jump = (2, 1) -jump_simple_backwards.output = [1, 1, 2] + def compare_jump_output(self, expected, received): + if received != expected: + self.fail( "Outputs don't match:\n" + + "Expected: " + repr(expected) + "\n" + + "Received: " + repr(received)) -def jump_out_of_block_forwards(output): - for i in 1, 2: + def run_test(self, func, jumpFrom, jumpTo, expected, error=None): + tracer = JumpTracer(func, jumpFrom, jumpTo) + sys.settrace(tracer.trace) + output = [] + if error is None: + func(output) + else: + with self.assertRaisesRegex(*error): + func(output) + sys.settrace(None) + self.compare_jump_output(expected, output) + + def jump_test(jumpFrom, jumpTo, expected, error=None): + """Decorator that creates a test that makes a jump + from one place to another in the following code. + """ + def decorator(func): + @wraps(func) + def test(self): + # +1 to compensate a decorator line + self.run_test(func, jumpFrom+1, jumpTo+1, expected, error) + return test + return decorator + + ## The first set of 'jump' tests are for things that are allowed: + + @jump_test(1, 3, [3]) + def test_jump_simple_forwards(output): + output.append(1) output.append(2) - for j in [3]: # Also tests jumping over a block - output.append(4) - output.append(5) - -jump_out_of_block_forwards.jump = (3, 5) -jump_out_of_block_forwards.output = [2, 5] - -def jump_out_of_block_backwards(output): - output.append(1) - for i in [1]: output.append(3) - for j in [2]: # Also tests jumping over a block - output.append(5) - output.append(6) - output.append(7) -jump_out_of_block_backwards.jump = (6, 1) -jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7] + @jump_test(2, 1, [1, 1, 2]) + def test_jump_simple_backwards(output): + output.append(1) + output.append(2) -def jump_to_codeless_line(output): - output.append(1) - # Jumping to this line should skip to the next one. - output.append(3) + @jump_test(3, 5, [2, 5]) + def test_jump_out_of_block_forwards(output): + for i in 1, 2: + output.append(2) + for j in [3]: # Also tests jumping over a block + output.append(4) + output.append(5) + + @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7]) + def test_jump_out_of_block_backwards(output): + output.append(1) + for i in [1]: + output.append(3) + for j in [2]: # Also tests jumping over a block + output.append(5) + output.append(6) + output.append(7) -jump_to_codeless_line.jump = (1, 2) -jump_to_codeless_line.output = [3] + @jump_test(1, 2, [3]) + def test_jump_to_codeless_line(output): + output.append(1) + # Jumping to this line should skip to the next one. + output.append(3) -def jump_to_same_line(output): - output.append(1) - output.append(2) - output.append(3) + @jump_test(2, 2, [1, 2, 3]) + def test_jump_to_same_line(output): + output.append(1) + output.append(2) + output.append(3) -jump_to_same_line.jump = (2, 2) -jump_to_same_line.output = [1, 2, 3] + # Tests jumping within a finally block, and over one. + @jump_test(4, 9, [2, 9]) + def test_jump_in_nested_finally(output): + try: + output.append(2) + finally: + output.append(4) + try: + output.append(6) + finally: + output.append(8) + output.append(9) -# Tests jumping within a finally block, and over one. -def jump_in_nested_finally(output): - try: - output.append(2) - finally: - output.append(4) + @jump_test(6, 7, [2, 7], (ZeroDivisionError, '')) + def test_jump_in_nested_finally_2(output): try: + output.append(2) + 1/0 + return + finally: output.append(6) + output.append(7) + output.append(8) + + @jump_test(6, 11, [2, 11], (ZeroDivisionError, '')) + def test_jump_in_nested_finally_3(output): + try: + output.append(2) + 1/0 + return finally: - output.append(8) - output.append(9) + output.append(6) + try: + output.append(8) + finally: + output.append(10) + output.append(11) + output.append(12) + + @jump_test(3, 4, [1, 4]) + def test_jump_infinite_while_loop(output): + output.append(1) + while True: + output.append(3) + output.append(4) -jump_in_nested_finally.jump = (4, 9) -jump_in_nested_finally.output = [2, 9] + @jump_test(2, 3, [1, 3]) + def test_jump_forwards_out_of_with_block(output): + with tracecontext(output, 1): + output.append(2) + output.append(3) -def jump_infinite_while_loop(output): - output.append(1) - while 1: - output.append(2) - output.append(3) + @jump_test(3, 1, [1, 2, 1, 2, 3, -2]) + def test_jump_backwards_out_of_with_block(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) -jump_infinite_while_loop.jump = (3, 4) -jump_infinite_while_loop.output = [1, 3] + @jump_test(2, 5, [5]) + def test_jump_forwards_out_of_try_finally_block(output): + try: + output.append(2) + finally: + output.append(4) + output.append(5) -# The second set of 'jump' tests are for things that are not allowed: + @jump_test(3, 1, [1, 1, 3, 5]) + def test_jump_backwards_out_of_try_finally_block(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) -def no_jump_too_far_forwards(output): - try: - output.append(2) - output.append(3) - except ValueError as e: - output.append('after' in str(e)) + @jump_test(2, 6, [6]) + def test_jump_forwards_out_of_try_except_block(output): + try: + output.append(2) + except: + output.append(4) + raise + output.append(6) -no_jump_too_far_forwards.jump = (3, 6) -no_jump_too_far_forwards.output = [2, True] + @jump_test(3, 1, [1, 1, 3]) + def test_jump_backwards_out_of_try_except_block(output): + output.append(1) + try: + output.append(3) + except: + output.append(5) + raise -def no_jump_too_far_backwards(output): - try: - output.append(2) - output.append(3) - except ValueError as e: - output.append('before' in str(e)) + @jump_test(5, 7, [4, 7, 8]) + def test_jump_between_except_blocks(output): + try: + 1/0 + except ZeroDivisionError: + output.append(4) + output.append(5) + except FloatingPointError: + output.append(7) + output.append(8) -no_jump_too_far_backwards.jump = (3, -1) -no_jump_too_far_backwards.output = [2, True] + @jump_test(5, 6, [4, 6, 7]) + def test_jump_within_except_block(output): + try: + 1/0 + except: + output.append(4) + output.append(5) + output.append(6) + output.append(7) -# Test each kind of 'except' line. -def no_jump_to_except_1(output): - try: - output.append(2) - except: - e = sys.exc_info()[1] - output.append('except' in str(e)) + @jump_test(8, 11, [1, 3, 5, 11, 12]) + def test_jump_out_of_complex_nested_blocks(output): + output.append(1) + for i in [1]: + output.append(3) + for j in [1, 2]: + output.append(5) + try: + for k in [1, 2]: + output.append(8) + finally: + output.append(10) + output.append(11) + output.append(12) + + @jump_test(3, 5, [1, 2, 5]) + def test_jump_out_of_with_assignment(output): + output.append(1) + with tracecontext(output, 2) \ + as x: + output.append(4) + output.append(5) -no_jump_to_except_1.jump = (2, 3) -no_jump_to_except_1.output = [True] + @jump_test(3, 6, [1, 6, 8, 9]) + def test_jump_over_return_in_try_finally_block(output): + output.append(1) + try: + output.append(3) + if not output: # always false + return + output.append(6) + finally: + output.append(8) + output.append(9) -def no_jump_to_except_2(output): - try: + @jump_test(5, 8, [1, 3, 8, 10, 11, 13]) + def test_jump_over_break_in_try_finally_block(output): + output.append(1) + while True: + output.append(3) + try: + output.append(5) + if not output: # always false + break + output.append(8) + finally: + output.append(10) + output.append(11) + break + output.append(13) + + # The second set of 'jump' tests are for things that are not allowed: + + @jump_test(2, 3, [1], (ValueError, 'after')) + def test_no_jump_too_far_forwards(output): + output.append(1) output.append(2) - except ValueError: - e = sys.exc_info()[1] - output.append('except' in str(e)) -no_jump_to_except_2.jump = (2, 3) -no_jump_to_except_2.output = [True] - -def no_jump_to_except_3(output): - try: + @jump_test(2, -2, [1], (ValueError, 'before')) + def test_no_jump_too_far_backwards(output): + output.append(1) output.append(2) - except ValueError as e: - output.append('except' in str(e)) -no_jump_to_except_3.jump = (2, 3) -no_jump_to_except_3.output = [True] + # Test each kind of 'except' line. + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_1(output): + try: + output.append(2) + except: + output.append(4) + raise -def no_jump_to_except_4(output): - try: - output.append(2) - except (ValueError, RuntimeError) as e: - output.append('except' in str(e)) + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_2(output): + try: + output.append(2) + except ValueError: + output.append(4) + raise -no_jump_to_except_4.jump = (2, 3) -no_jump_to_except_4.output = [True] + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_3(output): + try: + output.append(2) + except ValueError as e: + output.append(4) + raise e -def no_jump_forwards_into_block(output): - try: - output.append(2) - for i in 1, 2: + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_4(output): + try: + output.append(2) + except (ValueError, RuntimeError) as e: output.append(4) - except ValueError as e: - output.append('into' in str(e)) + raise e -no_jump_forwards_into_block.jump = (2, 4) -no_jump_forwards_into_block.output = [True] + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_for_block(output): + output.append(1) + for i in 1, 2: + output.append(3) -def no_jump_backwards_into_block(output): - try: + @jump_test(3, 2, [2, 2], (ValueError, 'into')) + def test_no_jump_backwards_into_for_block(output): for i in 1, 2: + output.append(2) + output.append(3) + + @jump_test(2, 4, [], (ValueError, 'into')) + def test_no_jump_forwards_into_while_block(output): + i = 1 + output.append(2) + while i <= 2: + output.append(4) + i += 1 + + @jump_test(5, 3, [3, 3], (ValueError, 'into')) + def test_no_jump_backwards_into_while_block(output): + i = 1 + while i <= 2: output.append(3) - output.append(4) - except ValueError as e: - output.append('into' in str(e)) + i += 1 + output.append(5) -no_jump_backwards_into_block.jump = (4, 3) -no_jump_backwards_into_block.output = [3, 3, True] + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_with_block(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) -def no_jump_into_finally_block(output): - try: + @jump_test(3, 2, [1, 2, -1], (ValueError, 'into')) + def test_no_jump_backwards_into_with_block(output): + with tracecontext(output, 1): + output.append(2) + output.append(3) + + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_try_finally_block(output): + output.append(1) try: output.append(3) - x = 1 finally: - output.append(6) - except ValueError as e: - output.append('finally' in str(e)) + output.append(5) -no_jump_into_finally_block.jump = (4, 6) -no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs + @jump_test(5, 2, [2, 4], (ValueError, 'into')) + def test_no_jump_backwards_into_try_finally_block(output): + try: + output.append(2) + finally: + output.append(4) + output.append(5) -def no_jump_out_of_finally_block(output): - try: + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_try_except_block(output): + output.append(1) try: output.append(3) - finally: + except: output.append(5) - output.append(6) - except ValueError as e: - output.append('finally' in str(e)) + raise -no_jump_out_of_finally_block.jump = (5, 1) -no_jump_out_of_finally_block.output = [3, True] + @jump_test(6, 2, [2], (ValueError, 'into')) + def test_no_jump_backwards_into_try_except_block(output): + try: + output.append(2) + except: + output.append(4) + raise + output.append(6) -# This verifies the line-numbers-must-be-integers rule. -def no_jump_to_non_integers(output): - try: - output.append(2) - except ValueError as e: - output.append('integer' in str(e)) + # 'except' with a variable creates an implicit finally block + @jump_test(5, 7, [4], (ValueError, 'into')) + def test_no_jump_between_except_blocks_2(output): + try: + 1/0 + except ZeroDivisionError: + output.append(4) + output.append(5) + except FloatingPointError as e: + output.append(7) + output.append(8) -no_jump_to_non_integers.jump = (2, "Spam") -no_jump_to_non_integers.output = [True] + @jump_test(3, 6, [2, 5, 6], (ValueError, 'finally')) + def test_no_jump_into_finally_block(output): + try: + output.append(2) + output.append(3) + finally: # still executed if the jump is failed + output.append(5) + output.append(6) + output.append(7) -def jump_across_with(output): - with open(support.TESTFN, "wb") as fp: - pass - with open(support.TESTFN, "wb") as fp: - pass -jump_across_with.jump = (1, 3) -jump_across_with.output = [] + @jump_test(1, 5, [], (ValueError, 'finally')) + def test_no_jump_into_finally_block_2(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) -# This verifies that you can't set f_lineno via _getframe or similar -# trickery. -def no_jump_without_trace_function(): - try: - previous_frame = sys._getframe().f_back - previous_frame.f_lineno = previous_frame.f_lineno - except ValueError as e: - # This is the exception we wanted; make sure the error message - # talks about trace functions. - if 'trace' not in str(e): - raise - else: - # Something's wrong - the expected exception wasn't raised. - raise RuntimeError("Trace-function-less jump failed to fail") + @jump_test(5, 1, [1, 3], (ValueError, 'finally')) + def test_no_jump_out_of_finally_block(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) + @jump_test(2, 4, [1, 4, 5, -4]) + def test_jump_across_with(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) + with tracecontext(output, 4): + output.append(5) -class JumpTestCase(unittest.TestCase): - def setUp(self): - self.addCleanup(sys.settrace, sys.gettrace()) - sys.settrace(None) + @jump_test(3, 5, [1, 2, -2], (ValueError, 'into')) + def test_jump_across_with_2(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) + with tracecontext(output, 4): + output.append(5) - def compare_jump_output(self, expected, received): - if received != expected: - self.fail( "Outputs don't match:\n" + - "Expected: " + repr(expected) + "\n" + - "Received: " + repr(received)) + def test_no_jump_to_non_integers(self): + self.run_test(no_jump_to_non_integers, 2, "Spam", [True]) - def run_test(self, func): - tracer = JumpTracer(func) - sys.settrace(tracer.trace) - output = [] - func(output) - sys.settrace(None) - self.compare_jump_output(func.output, output) - - def test_01_jump_simple_forwards(self): - self.run_test(jump_simple_forwards) - def test_02_jump_simple_backwards(self): - self.run_test(jump_simple_backwards) - def test_03_jump_out_of_block_forwards(self): - self.run_test(jump_out_of_block_forwards) - def test_04_jump_out_of_block_backwards(self): - self.run_test(jump_out_of_block_backwards) - def test_05_jump_to_codeless_line(self): - self.run_test(jump_to_codeless_line) - def test_06_jump_to_same_line(self): - self.run_test(jump_to_same_line) - def test_07_jump_in_nested_finally(self): - self.run_test(jump_in_nested_finally) - def test_jump_infinite_while_loop(self): - self.run_test(jump_infinite_while_loop) - def test_08_no_jump_too_far_forwards(self): - self.run_test(no_jump_too_far_forwards) - def test_09_no_jump_too_far_backwards(self): - self.run_test(no_jump_too_far_backwards) - def test_10_no_jump_to_except_1(self): - self.run_test(no_jump_to_except_1) - def test_11_no_jump_to_except_2(self): - self.run_test(no_jump_to_except_2) - def test_12_no_jump_to_except_3(self): - self.run_test(no_jump_to_except_3) - def test_13_no_jump_to_except_4(self): - self.run_test(no_jump_to_except_4) - def test_14_no_jump_forwards_into_block(self): - self.run_test(no_jump_forwards_into_block) - def test_15_no_jump_backwards_into_block(self): - self.run_test(no_jump_backwards_into_block) - def test_16_no_jump_into_finally_block(self): - self.run_test(no_jump_into_finally_block) - def test_17_no_jump_out_of_finally_block(self): - self.run_test(no_jump_out_of_finally_block) - def test_18_no_jump_to_non_integers(self): - self.run_test(no_jump_to_non_integers) - def test_19_no_jump_without_trace_function(self): + def test_no_jump_without_trace_function(self): # Must set sys.settrace(None) in setUp(), else condition is not # triggered. no_jump_without_trace_function() - def test_jump_across_with(self): - self.addCleanup(support.unlink, support.TESTFN) - self.run_test(jump_across_with) - def test_20_large_function(self): + def test_large_function(self): d = {} exec("""def f(output): # line 0 x = 0 # line 1 @@ -863,10 +1033,7 @@ def test_20_large_function(self): output.append(x) # line 1007 return""" % ('\n' * 1000,), d) f = d['f'] - - f.jump = (2, 1007) - f.output = [0] - self.run_test(f) + self.run_test(f, 2, 1007, [0]) def test_jump_to_firstlineno(self): # This tests that PDB can jump back to the first line in a @@ -880,8 +1047,7 @@ def test_jump_to_firstlineno(self): """, "", "exec") class fake_function: __code__ = code - jump = (2, 0) - tracer = JumpTracer(fake_function) + tracer = JumpTracer(fake_function, 2, 0) sys.settrace(tracer.trace) namespace = {"output": []} exec(code, namespace) @@ -889,14 +1055,5 @@ class fake_function: self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"]) -def test_main(): - support.run_unittest( - TraceTestCase, - SkipLineEventsTraceTestCase, - TraceOpcodesTestCase, - RaisingTraceFuncTestCase, - JumpTestCase - ) - if __name__ == "__main__": - test_main() + unittest.main() From solipsis at pitrou.net Wed Dec 27 04:14:42 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 27 Dec 2017 09:14:42 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20171227091442.20442.9C548C840977BA9F@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, 0, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogUivvWC', '--timeout', '7200'] From webhook-mailer at python.org Wed Dec 27 14:31:50 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 27 Dec 2017 19:31:50 -0000 Subject: [Python-checkins] [3.6] bpo-32416: Refactor tests for the f_lineno setter and add new tests. (GH-4991). (#5016) Message-ID: https://github.com/python/cpython/commit/ea98eba3465fff2b191610cea253d43000c84b4a commit: ea98eba3465fff2b191610cea253d43000c84b4a branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2017-12-27T21:31:47+02:00 summary: [3.6] bpo-32416: Refactor tests for the f_lineno setter and add new tests. (GH-4991). (#5016) (cherry picked from commit 53f9135667226f33e049e327db60fb033afbd77a) files: M Lib/test/test_sys_settrace.py diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index ec537bee91c..49fbf4d750d 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -5,6 +5,19 @@ import sys import difflib import gc +from functools import wraps + +class tracecontext: + """Contex manager that traces its enter and exit.""" + def __init__(self, output, value): + self.output = output + self.value = value + + def __enter__(self): + self.output.append(self.value) + + def __exit__(self, *exc_info): + self.output.append(-self.value) # A very basic example. If this fails, we're in deep trouble. def basic(): @@ -495,14 +508,12 @@ def g(frame, event, arg): # command (aka. "Set next statement"). class JumpTracer: - """Defines a trace function that jumps from one place to another, - with the source and destination lines of the jump being defined by - the 'jump' property of the function under test.""" + """Defines a trace function that jumps from one place to another.""" - def __init__(self, function): + def __init__(self, function, jumpFrom, jumpTo): self.function = function - self.jumpFrom = function.jump[0] - self.jumpTo = function.jump[1] + self.jumpFrom = jumpFrom + self.jumpTo = jumpTo self.done = False def trace(self, frame, event, arg): @@ -518,294 +529,453 @@ def trace(self, frame, event, arg): self.done = True return self.trace -# The first set of 'jump' tests are for things that are allowed: +# This verifies the line-numbers-must-be-integers rule. +def no_jump_to_non_integers(output): + try: + output.append(2) + except ValueError as e: + output.append('integer' in str(e)) -def jump_simple_forwards(output): - output.append(1) - output.append(2) - output.append(3) +# This verifies that you can't set f_lineno via _getframe or similar +# trickery. +def no_jump_without_trace_function(): + try: + previous_frame = sys._getframe().f_back + previous_frame.f_lineno = previous_frame.f_lineno + except ValueError as e: + # This is the exception we wanted; make sure the error message + # talks about trace functions. + if 'trace' not in str(e): + raise + else: + # Something's wrong - the expected exception wasn't raised. + raise AssertionError("Trace-function-less jump failed to fail") -jump_simple_forwards.jump = (1, 3) -jump_simple_forwards.output = [3] -def jump_simple_backwards(output): - output.append(1) - output.append(2) +class JumpTestCase(unittest.TestCase): + def setUp(self): + self.addCleanup(sys.settrace, sys.gettrace()) + sys.settrace(None) -jump_simple_backwards.jump = (2, 1) -jump_simple_backwards.output = [1, 1, 2] + def compare_jump_output(self, expected, received): + if received != expected: + self.fail( "Outputs don't match:\n" + + "Expected: " + repr(expected) + "\n" + + "Received: " + repr(received)) -def jump_out_of_block_forwards(output): - for i in 1, 2: + def run_test(self, func, jumpFrom, jumpTo, expected, error=None): + tracer = JumpTracer(func, jumpFrom, jumpTo) + sys.settrace(tracer.trace) + output = [] + if error is None: + func(output) + else: + with self.assertRaisesRegex(*error): + func(output) + sys.settrace(None) + self.compare_jump_output(expected, output) + + def jump_test(jumpFrom, jumpTo, expected, error=None): + """Decorator that creates a test that makes a jump + from one place to another in the following code. + """ + def decorator(func): + @wraps(func) + def test(self): + # +1 to compensate a decorator line + self.run_test(func, jumpFrom+1, jumpTo+1, expected, error) + return test + return decorator + + ## The first set of 'jump' tests are for things that are allowed: + + @jump_test(1, 3, [3]) + def test_jump_simple_forwards(output): + output.append(1) output.append(2) - for j in [3]: # Also tests jumping over a block - output.append(4) - output.append(5) - -jump_out_of_block_forwards.jump = (3, 5) -jump_out_of_block_forwards.output = [2, 5] - -def jump_out_of_block_backwards(output): - output.append(1) - for i in [1]: output.append(3) - for j in [2]: # Also tests jumping over a block - output.append(5) - output.append(6) - output.append(7) -jump_out_of_block_backwards.jump = (6, 1) -jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7] + @jump_test(2, 1, [1, 1, 2]) + def test_jump_simple_backwards(output): + output.append(1) + output.append(2) -def jump_to_codeless_line(output): - output.append(1) - # Jumping to this line should skip to the next one. - output.append(3) + @jump_test(3, 5, [2, 5]) + def test_jump_out_of_block_forwards(output): + for i in 1, 2: + output.append(2) + for j in [3]: # Also tests jumping over a block + output.append(4) + output.append(5) + + @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7]) + def test_jump_out_of_block_backwards(output): + output.append(1) + for i in [1]: + output.append(3) + for j in [2]: # Also tests jumping over a block + output.append(5) + output.append(6) + output.append(7) -jump_to_codeless_line.jump = (1, 2) -jump_to_codeless_line.output = [3] + @jump_test(1, 2, [3]) + def test_jump_to_codeless_line(output): + output.append(1) + # Jumping to this line should skip to the next one. + output.append(3) -def jump_to_same_line(output): - output.append(1) - output.append(2) - output.append(3) + @jump_test(2, 2, [1, 2, 3]) + def test_jump_to_same_line(output): + output.append(1) + output.append(2) + output.append(3) -jump_to_same_line.jump = (2, 2) -jump_to_same_line.output = [1, 2, 3] + # Tests jumping within a finally block, and over one. + @jump_test(4, 9, [2, 9]) + def test_jump_in_nested_finally(output): + try: + output.append(2) + finally: + output.append(4) + try: + output.append(6) + finally: + output.append(8) + output.append(9) -# Tests jumping within a finally block, and over one. -def jump_in_nested_finally(output): - try: - output.append(2) - finally: - output.append(4) + @jump_test(6, 7, [2, 7], (ZeroDivisionError, '')) + def test_jump_in_nested_finally_2(output): try: + output.append(2) + 1/0 + return + finally: output.append(6) + output.append(7) + output.append(8) + + @jump_test(6, 11, [2, 11], (ZeroDivisionError, '')) + def test_jump_in_nested_finally_3(output): + try: + output.append(2) + 1/0 + return finally: - output.append(8) - output.append(9) + output.append(6) + try: + output.append(8) + finally: + output.append(10) + output.append(11) + output.append(12) + + @jump_test(3, 4, [1, 4]) + def test_jump_infinite_while_loop(output): + output.append(1) + while True: + output.append(3) + output.append(4) -jump_in_nested_finally.jump = (4, 9) -jump_in_nested_finally.output = [2, 9] + @jump_test(2, 3, [1, 3]) + def test_jump_forwards_out_of_with_block(output): + with tracecontext(output, 1): + output.append(2) + output.append(3) -def jump_infinite_while_loop(output): - output.append(1) - while 1: - output.append(2) - output.append(3) + @jump_test(3, 1, [1, 2, 1, 2, 3, -2]) + def test_jump_backwards_out_of_with_block(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) -jump_infinite_while_loop.jump = (3, 4) -jump_infinite_while_loop.output = [1, 3] + @jump_test(2, 5, [5]) + def test_jump_forwards_out_of_try_finally_block(output): + try: + output.append(2) + finally: + output.append(4) + output.append(5) -# The second set of 'jump' tests are for things that are not allowed: + @jump_test(3, 1, [1, 1, 3, 5]) + def test_jump_backwards_out_of_try_finally_block(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) -def no_jump_too_far_forwards(output): - try: - output.append(2) - output.append(3) - except ValueError as e: - output.append('after' in str(e)) + @jump_test(2, 6, [6]) + def test_jump_forwards_out_of_try_except_block(output): + try: + output.append(2) + except: + output.append(4) + raise + output.append(6) -no_jump_too_far_forwards.jump = (3, 6) -no_jump_too_far_forwards.output = [2, True] + @jump_test(3, 1, [1, 1, 3]) + def test_jump_backwards_out_of_try_except_block(output): + output.append(1) + try: + output.append(3) + except: + output.append(5) + raise -def no_jump_too_far_backwards(output): - try: - output.append(2) - output.append(3) - except ValueError as e: - output.append('before' in str(e)) + @jump_test(5, 7, [4, 7, 8]) + def test_jump_between_except_blocks(output): + try: + 1/0 + except ZeroDivisionError: + output.append(4) + output.append(5) + except FloatingPointError: + output.append(7) + output.append(8) -no_jump_too_far_backwards.jump = (3, -1) -no_jump_too_far_backwards.output = [2, True] + @jump_test(5, 6, [4, 6, 7]) + def test_jump_within_except_block(output): + try: + 1/0 + except: + output.append(4) + output.append(5) + output.append(6) + output.append(7) -# Test each kind of 'except' line. -def no_jump_to_except_1(output): - try: - output.append(2) - except: - e = sys.exc_info()[1] - output.append('except' in str(e)) + @jump_test(8, 11, [1, 3, 5, 11, 12]) + def test_jump_out_of_complex_nested_blocks(output): + output.append(1) + for i in [1]: + output.append(3) + for j in [1, 2]: + output.append(5) + try: + for k in [1, 2]: + output.append(8) + finally: + output.append(10) + output.append(11) + output.append(12) + + @jump_test(3, 5, [1, 2, 5]) + def test_jump_out_of_with_assignment(output): + output.append(1) + with tracecontext(output, 2) \ + as x: + output.append(4) + output.append(5) -no_jump_to_except_1.jump = (2, 3) -no_jump_to_except_1.output = [True] + @jump_test(3, 6, [1, 6, 8, 9]) + def test_jump_over_return_in_try_finally_block(output): + output.append(1) + try: + output.append(3) + if not output: # always false + return + output.append(6) + finally: + output.append(8) + output.append(9) -def no_jump_to_except_2(output): - try: + @jump_test(5, 8, [1, 3, 8, 10, 11, 13]) + def test_jump_over_break_in_try_finally_block(output): + output.append(1) + while True: + output.append(3) + try: + output.append(5) + if not output: # always false + break + output.append(8) + finally: + output.append(10) + output.append(11) + break + output.append(13) + + # The second set of 'jump' tests are for things that are not allowed: + + @jump_test(2, 3, [1], (ValueError, 'after')) + def test_no_jump_too_far_forwards(output): + output.append(1) output.append(2) - except ValueError: - e = sys.exc_info()[1] - output.append('except' in str(e)) -no_jump_to_except_2.jump = (2, 3) -no_jump_to_except_2.output = [True] - -def no_jump_to_except_3(output): - try: + @jump_test(2, -2, [1], (ValueError, 'before')) + def test_no_jump_too_far_backwards(output): + output.append(1) output.append(2) - except ValueError as e: - output.append('except' in str(e)) -no_jump_to_except_3.jump = (2, 3) -no_jump_to_except_3.output = [True] + # Test each kind of 'except' line. + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_1(output): + try: + output.append(2) + except: + output.append(4) + raise -def no_jump_to_except_4(output): - try: - output.append(2) - except (ValueError, RuntimeError) as e: - output.append('except' in str(e)) + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_2(output): + try: + output.append(2) + except ValueError: + output.append(4) + raise -no_jump_to_except_4.jump = (2, 3) -no_jump_to_except_4.output = [True] + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_3(output): + try: + output.append(2) + except ValueError as e: + output.append(4) + raise e -def no_jump_forwards_into_block(output): - try: - output.append(2) - for i in 1, 2: + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_4(output): + try: + output.append(2) + except (ValueError, RuntimeError) as e: output.append(4) - except ValueError as e: - output.append('into' in str(e)) + raise e -no_jump_forwards_into_block.jump = (2, 4) -no_jump_forwards_into_block.output = [True] + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_for_block(output): + output.append(1) + for i in 1, 2: + output.append(3) -def no_jump_backwards_into_block(output): - try: + @jump_test(3, 2, [2, 2], (ValueError, 'into')) + def test_no_jump_backwards_into_for_block(output): for i in 1, 2: + output.append(2) + output.append(3) + + @jump_test(2, 4, [], (ValueError, 'into')) + def test_no_jump_forwards_into_while_block(output): + i = 1 + output.append(2) + while i <= 2: + output.append(4) + i += 1 + + @jump_test(5, 3, [3, 3], (ValueError, 'into')) + def test_no_jump_backwards_into_while_block(output): + i = 1 + while i <= 2: output.append(3) - output.append(4) - except ValueError as e: - output.append('into' in str(e)) + i += 1 + output.append(5) -no_jump_backwards_into_block.jump = (4, 3) -no_jump_backwards_into_block.output = [3, 3, True] + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_with_block(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) -def no_jump_into_finally_block(output): - try: + @jump_test(3, 2, [1, 2, -1], (ValueError, 'into')) + def test_no_jump_backwards_into_with_block(output): + with tracecontext(output, 1): + output.append(2) + output.append(3) + + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_try_finally_block(output): + output.append(1) try: output.append(3) - x = 1 finally: - output.append(6) - except ValueError as e: - output.append('finally' in str(e)) + output.append(5) -no_jump_into_finally_block.jump = (4, 6) -no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs + @jump_test(5, 2, [2, 4], (ValueError, 'into')) + def test_no_jump_backwards_into_try_finally_block(output): + try: + output.append(2) + finally: + output.append(4) + output.append(5) -def no_jump_out_of_finally_block(output): - try: + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_try_except_block(output): + output.append(1) try: output.append(3) - finally: + except: output.append(5) - output.append(6) - except ValueError as e: - output.append('finally' in str(e)) + raise -no_jump_out_of_finally_block.jump = (5, 1) -no_jump_out_of_finally_block.output = [3, True] + @jump_test(6, 2, [2], (ValueError, 'into')) + def test_no_jump_backwards_into_try_except_block(output): + try: + output.append(2) + except: + output.append(4) + raise + output.append(6) -# This verifies the line-numbers-must-be-integers rule. -def no_jump_to_non_integers(output): - try: - output.append(2) - except ValueError as e: - output.append('integer' in str(e)) + # 'except' with a variable creates an implicit finally block + @jump_test(5, 7, [4], (ValueError, 'into')) + def test_no_jump_between_except_blocks_2(output): + try: + 1/0 + except ZeroDivisionError: + output.append(4) + output.append(5) + except FloatingPointError as e: + output.append(7) + output.append(8) -no_jump_to_non_integers.jump = (2, "Spam") -no_jump_to_non_integers.output = [True] + @jump_test(3, 6, [2, 5, 6], (ValueError, 'finally')) + def test_no_jump_into_finally_block(output): + try: + output.append(2) + output.append(3) + finally: # still executed if the jump is failed + output.append(5) + output.append(6) + output.append(7) -def jump_across_with(output): - with open(support.TESTFN, "wb") as fp: - pass - with open(support.TESTFN, "wb") as fp: - pass -jump_across_with.jump = (1, 3) -jump_across_with.output = [] + @jump_test(1, 5, [], (ValueError, 'finally')) + def test_no_jump_into_finally_block_2(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) -# This verifies that you can't set f_lineno via _getframe or similar -# trickery. -def no_jump_without_trace_function(): - try: - previous_frame = sys._getframe().f_back - previous_frame.f_lineno = previous_frame.f_lineno - except ValueError as e: - # This is the exception we wanted; make sure the error message - # talks about trace functions. - if 'trace' not in str(e): - raise - else: - # Something's wrong - the expected exception wasn't raised. - raise RuntimeError("Trace-function-less jump failed to fail") + @jump_test(5, 1, [1, 3], (ValueError, 'finally')) + def test_no_jump_out_of_finally_block(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) + @jump_test(2, 4, [1, 4, 5, -4]) + def test_jump_across_with(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) + with tracecontext(output, 4): + output.append(5) -class JumpTestCase(unittest.TestCase): - def setUp(self): - self.addCleanup(sys.settrace, sys.gettrace()) - sys.settrace(None) + @jump_test(3, 5, [1, 2, -2], (ValueError, 'into')) + def test_jump_across_with_2(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) + with tracecontext(output, 4): + output.append(5) - def compare_jump_output(self, expected, received): - if received != expected: - self.fail( "Outputs don't match:\n" + - "Expected: " + repr(expected) + "\n" + - "Received: " + repr(received)) + def test_no_jump_to_non_integers(self): + self.run_test(no_jump_to_non_integers, 2, "Spam", [True]) - def run_test(self, func): - tracer = JumpTracer(func) - sys.settrace(tracer.trace) - output = [] - func(output) - sys.settrace(None) - self.compare_jump_output(func.output, output) - - def test_01_jump_simple_forwards(self): - self.run_test(jump_simple_forwards) - def test_02_jump_simple_backwards(self): - self.run_test(jump_simple_backwards) - def test_03_jump_out_of_block_forwards(self): - self.run_test(jump_out_of_block_forwards) - def test_04_jump_out_of_block_backwards(self): - self.run_test(jump_out_of_block_backwards) - def test_05_jump_to_codeless_line(self): - self.run_test(jump_to_codeless_line) - def test_06_jump_to_same_line(self): - self.run_test(jump_to_same_line) - def test_07_jump_in_nested_finally(self): - self.run_test(jump_in_nested_finally) - def test_jump_infinite_while_loop(self): - self.run_test(jump_infinite_while_loop) - def test_08_no_jump_too_far_forwards(self): - self.run_test(no_jump_too_far_forwards) - def test_09_no_jump_too_far_backwards(self): - self.run_test(no_jump_too_far_backwards) - def test_10_no_jump_to_except_1(self): - self.run_test(no_jump_to_except_1) - def test_11_no_jump_to_except_2(self): - self.run_test(no_jump_to_except_2) - def test_12_no_jump_to_except_3(self): - self.run_test(no_jump_to_except_3) - def test_13_no_jump_to_except_4(self): - self.run_test(no_jump_to_except_4) - def test_14_no_jump_forwards_into_block(self): - self.run_test(no_jump_forwards_into_block) - def test_15_no_jump_backwards_into_block(self): - self.run_test(no_jump_backwards_into_block) - def test_16_no_jump_into_finally_block(self): - self.run_test(no_jump_into_finally_block) - def test_17_no_jump_out_of_finally_block(self): - self.run_test(no_jump_out_of_finally_block) - def test_18_no_jump_to_non_integers(self): - self.run_test(no_jump_to_non_integers) - def test_19_no_jump_without_trace_function(self): + def test_no_jump_without_trace_function(self): # Must set sys.settrace(None) in setUp(), else condition is not # triggered. no_jump_without_trace_function() - def test_jump_across_with(self): - self.addCleanup(support.unlink, support.TESTFN) - self.run_test(jump_across_with) - def test_20_large_function(self): + def test_large_function(self): d = {} exec("""def f(output): # line 0 x = 0 # line 1 @@ -817,10 +987,7 @@ def test_20_large_function(self): output.append(x) # line 1007 return""" % ('\n' * 1000,), d) f = d['f'] - - f.jump = (2, 1007) - f.output = [0] - self.run_test(f) + self.run_test(f, 2, 1007, [0]) def test_jump_to_firstlineno(self): # This tests that PDB can jump back to the first line in a @@ -834,8 +1001,7 @@ def test_jump_to_firstlineno(self): """, "", "exec") class fake_function: __code__ = code - jump = (2, 0) - tracer = JumpTracer(fake_function) + tracer = JumpTracer(fake_function, 2, 0) sys.settrace(tracer.trace) namespace = {"output": []} exec(code, namespace) @@ -843,12 +1009,5 @@ class fake_function: self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"]) -def test_main(): - support.run_unittest( - TraceTestCase, - RaisingTraceFuncTestCase, - JumpTestCase - ) - if __name__ == "__main__": - test_main() + unittest.main() From webhook-mailer at python.org Wed Dec 27 14:32:06 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 27 Dec 2017 19:32:06 -0000 Subject: [Python-checkins] [2.7] bpo-32416: Refactor tests for the f_lineno setter and add new tests. (GH-4991). (#5017) Message-ID: https://github.com/python/cpython/commit/c60eca06adda4900e6b469d989e6082cda3a3004 commit: c60eca06adda4900e6b469d989e6082cda3a3004 branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2017-12-27T21:32:03+02:00 summary: [2.7] bpo-32416: Refactor tests for the f_lineno setter and add new tests. (GH-4991). (#5017) (cherry picked from commit 53f9135667226f33e049e327db60fb033afbd77a) files: M Lib/test/test_sys_settrace.py diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index cc9a5815e43..e5b380fbe0b 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -5,6 +5,19 @@ import sys import difflib import gc +from functools import wraps + +class tracecontext: + """Contex manager that traces its enter and exit.""" + def __init__(self, output, value): + self.output = output + self.value = value + + def __enter__(self): + self.output.append(self.value) + + def __exit__(self, *exc_info): + self.output.append(-self.value) # A very basic example. If this fails, we're in deep trouble. def basic(): @@ -467,14 +480,12 @@ def g(frame, why, extra): # command (aka. "Set next statement"). class JumpTracer: - """Defines a trace function that jumps from one place to another, - with the source and destination lines of the jump being defined by - the 'jump' property of the function under test.""" + """Defines a trace function that jumps from one place to another.""" - def __init__(self, function): + def __init__(self, function, jumpFrom, jumpTo): self.function = function - self.jumpFrom = function.jump[0] - self.jumpTo = function.jump[1] + self.jumpFrom = jumpFrom + self.jumpTo = jumpTo self.done = False def trace(self, frame, event, arg): @@ -490,288 +501,441 @@ def trace(self, frame, event, arg): self.done = True return self.trace -# The first set of 'jump' tests are for things that are allowed: +# This verifies the line-numbers-must-be-integers rule. +def no_jump_to_non_integers(output): + try: + output.append(2) + except ValueError as e: + output.append('integer' in str(e)) + +# This verifies that you can't set f_lineno via _getframe or similar +# trickery. +def no_jump_without_trace_function(): + try: + previous_frame = sys._getframe().f_back + previous_frame.f_lineno = previous_frame.f_lineno + except ValueError as e: + # This is the exception we wanted; make sure the error message + # talks about trace functions. + if 'trace' not in str(e): + raise + else: + # Something's wrong - the expected exception wasn't raised. + raise AssertionError("Trace-function-less jump failed to fail") -def jump_simple_forwards(output): - output.append(1) - output.append(2) - output.append(3) -jump_simple_forwards.jump = (1, 3) -jump_simple_forwards.output = [3] +class JumpTestCase(unittest.TestCase): + def setUp(self): + self.addCleanup(sys.settrace, sys.gettrace()) + sys.settrace(None) -def jump_simple_backwards(output): - output.append(1) - output.append(2) + def compare_jump_output(self, expected, received): + if received != expected: + self.fail( "Outputs don't match:\n" + + "Expected: " + repr(expected) + "\n" + + "Received: " + repr(received)) -jump_simple_backwards.jump = (2, 1) -jump_simple_backwards.output = [1, 1, 2] + def run_test(self, func, jumpFrom, jumpTo, expected, error=None): + tracer = JumpTracer(func, jumpFrom, jumpTo) + sys.settrace(tracer.trace) + output = [] + if error is None: + func(output) + else: + with self.assertRaisesRegexp(*error): + func(output) + sys.settrace(None) + self.compare_jump_output(expected, output) + + def jump_test(jumpFrom, jumpTo, expected, error=None): + """Decorator that creates a test that makes a jump + from one place to another in the following code. + """ + def decorator(func): + @wraps(func) + def test(self): + # +1 to compensate a decorator line + self.run_test(func, jumpFrom+1, jumpTo+1, expected, error) + return test + return decorator + + ## The first set of 'jump' tests are for things that are allowed: + + @jump_test(1, 3, [3]) + def test_jump_simple_forwards(output): + output.append(1) + output.append(2) + output.append(3) -def jump_out_of_block_forwards(output): - for i in 1, 2: + @jump_test(2, 1, [1, 1, 2]) + def test_jump_simple_backwards(output): + output.append(1) output.append(2) - for j in [3]: # Also tests jumping over a block - output.append(4) - output.append(5) -jump_out_of_block_forwards.jump = (3, 5) -jump_out_of_block_forwards.output = [2, 5] + @jump_test(3, 5, [2, 5]) + def test_jump_out_of_block_forwards(output): + for i in 1, 2: + output.append(2) + for j in [3]: # Also tests jumping over a block + output.append(4) + output.append(5) + + @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7]) + def test_jump_out_of_block_backwards(output): + output.append(1) + for i in [1]: + output.append(3) + for j in [2]: # Also tests jumping over a block + output.append(5) + output.append(6) + output.append(7) -def jump_out_of_block_backwards(output): - output.append(1) - for i in [1]: + @jump_test(1, 2, [3]) + def test_jump_to_codeless_line(output): + output.append(1) + # Jumping to this line should skip to the next one. output.append(3) - for j in [2]: # Also tests jumping over a block - output.append(5) - output.append(6) - output.append(7) -jump_out_of_block_backwards.jump = (6, 1) -jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7] + @jump_test(2, 2, [1, 2, 3]) + def test_jump_to_same_line(output): + output.append(1) + output.append(2) + output.append(3) -def jump_to_codeless_line(output): - output.append(1) - # Jumping to this line should skip to the next one. - output.append(3) + # Tests jumping within a finally block, and over one. + @jump_test(4, 9, [2, 9]) + def test_jump_in_nested_finally(output): + try: + output.append(2) + finally: + output.append(4) + try: + output.append(6) + finally: + output.append(8) + output.append(9) + + @jump_test(6, 7, [2, 7], (ZeroDivisionError, '')) + def test_jump_in_nested_finally_2(output): + try: + output.append(2) + 1/0 + return + finally: + output.append(6) + output.append(7) + output.append(8) -jump_to_codeless_line.jump = (1, 2) -jump_to_codeless_line.output = [3] + @jump_test(6, 11, [2, 11], (ZeroDivisionError, '')) + def test_jump_in_nested_finally_3(output): + try: + output.append(2) + 1/0 + return + finally: + output.append(6) + try: + output.append(8) + finally: + output.append(10) + output.append(11) + output.append(12) + + @jump_test(3, 4, [1, 4]) + def test_jump_infinite_while_loop(output): + output.append(1) + while True: + output.append(3) + output.append(4) -def jump_to_same_line(output): - output.append(1) - output.append(2) - output.append(3) + @jump_test(2, 3, [1, 3]) + def test_jump_forwards_out_of_with_block(output): + with tracecontext(output, 1): + output.append(2) + output.append(3) -jump_to_same_line.jump = (2, 2) -jump_to_same_line.output = [1, 2, 3] + @jump_test(3, 1, [1, 2, 1, 2, 3, -2]) + def test_jump_backwards_out_of_with_block(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) -# Tests jumping within a finally block, and over one. -def jump_in_nested_finally(output): - try: - output.append(2) - finally: - output.append(4) + @jump_test(2, 5, [5]) + def test_jump_forwards_out_of_try_finally_block(output): try: - output.append(6) + output.append(2) finally: - output.append(8) - output.append(9) - -jump_in_nested_finally.jump = (4, 9) -jump_in_nested_finally.output = [2, 9] + output.append(4) + output.append(5) -def jump_infinite_while_loop(output): - output.append(1) - while 1: - output.append(2) - output.append(3) + @jump_test(3, 1, [1, 1, 3, 5]) + def test_jump_backwards_out_of_try_finally_block(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) -jump_infinite_while_loop.jump = (3, 4) -jump_infinite_while_loop.output = [1, 3] + @jump_test(2, 6, [6]) + def test_jump_forwards_out_of_try_except_block(output): + try: + output.append(2) + except: + output.append(4) + raise + output.append(6) -# The second set of 'jump' tests are for things that are not allowed: + @jump_test(3, 1, [1, 1, 3]) + def test_jump_backwards_out_of_try_except_block(output): + output.append(1) + try: + output.append(3) + except: + output.append(5) + raise -def no_jump_too_far_forwards(output): - try: - output.append(2) - output.append(3) - except ValueError, e: - output.append('after' in str(e)) + @jump_test(5, 7, [4, 7, 8]) + def test_jump_between_except_blocks(output): + try: + 1/0 + except ZeroDivisionError: + output.append(4) + output.append(5) + except FloatingPointError: + output.append(7) + output.append(8) -no_jump_too_far_forwards.jump = (3, 6) -no_jump_too_far_forwards.output = [2, True] + @jump_test(5, 6, [4, 6, 7]) + def test_jump_within_except_block(output): + try: + 1/0 + except: + output.append(4) + output.append(5) + output.append(6) + output.append(7) -def no_jump_too_far_backwards(output): - try: - output.append(2) - output.append(3) - except ValueError, e: - output.append('before' in str(e)) + @jump_test(8, 11, [1, 3, 5, 11, 12]) + def test_jump_out_of_complex_nested_blocks(output): + output.append(1) + for i in [1]: + output.append(3) + for j in [1, 2]: + output.append(5) + try: + for k in [1, 2]: + output.append(8) + finally: + output.append(10) + output.append(11) + output.append(12) + + @jump_test(3, 5, [1, 2, 5]) + def test_jump_out_of_with_assignment(output): + output.append(1) + with tracecontext(output, 2) \ + as x: + output.append(4) + output.append(5) -no_jump_too_far_backwards.jump = (3, -1) -no_jump_too_far_backwards.output = [2, True] + @jump_test(3, 6, [1, 6, 8, 9]) + def test_jump_over_return_in_try_finally_block(output): + output.append(1) + try: + output.append(3) + if not output: # always false + return + output.append(6) + finally: + output.append(8) + output.append(9) -# Test each kind of 'except' line. -def no_jump_to_except_1(output): - try: + @jump_test(5, 8, [1, 3, 8, 10, 11, 13]) + def test_jump_over_break_in_try_finally_block(output): + output.append(1) + while True: + output.append(3) + try: + output.append(5) + if not output: # always false + break + output.append(8) + finally: + output.append(10) + output.append(11) + break + output.append(13) + + # The second set of 'jump' tests are for things that are not allowed: + + @jump_test(2, 3, [1], (ValueError, 'after')) + def test_no_jump_too_far_forwards(output): + output.append(1) output.append(2) - except: - e = sys.exc_info()[1] - output.append('except' in str(e)) - -no_jump_to_except_1.jump = (2, 3) -no_jump_to_except_1.output = [True] -def no_jump_to_except_2(output): - try: + @jump_test(2, -2, [1], (ValueError, 'before')) + def test_no_jump_too_far_backwards(output): + output.append(1) output.append(2) - except ValueError: - e = sys.exc_info()[1] - output.append('except' in str(e)) -no_jump_to_except_2.jump = (2, 3) -no_jump_to_except_2.output = [True] + # Test each kind of 'except' line. + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_1(output): + try: + output.append(2) + except: + output.append(4) + raise + + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_2(output): + try: + output.append(2) + except ValueError: + output.append(4) + raise -def no_jump_to_except_3(output): - try: - output.append(2) - except ValueError, e: - output.append('except' in str(e)) + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_3(output): + try: + output.append(2) + except ValueError as e: + output.append(4) + raise e -no_jump_to_except_3.jump = (2, 3) -no_jump_to_except_3.output = [True] + @jump_test(2, 3, [4], (ValueError, 'except')) + def test_no_jump_to_except_4(output): + try: + output.append(2) + except (ValueError, RuntimeError) as e: + output.append(4) + raise e -def no_jump_to_except_4(output): - try: - output.append(2) - except (ValueError, RuntimeError), e: - output.append('except' in str(e)) + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_for_block(output): + output.append(1) + for i in 1, 2: + output.append(3) -no_jump_to_except_4.jump = (2, 3) -no_jump_to_except_4.output = [True] + @jump_test(3, 2, [2, 2], (ValueError, 'into')) + def test_no_jump_backwards_into_for_block(output): + for i in 1, 2: + output.append(2) + output.append(3) -def no_jump_forwards_into_block(output): - try: + @jump_test(2, 4, [], (ValueError, 'into')) + def test_no_jump_forwards_into_while_block(output): + i = 1 output.append(2) - for i in 1, 2: + while i <= 2: output.append(4) - except ValueError, e: - output.append('into' in str(e)) + i += 1 -no_jump_forwards_into_block.jump = (2, 4) -no_jump_forwards_into_block.output = [True] + @jump_test(5, 3, [3, 3], (ValueError, 'into')) + def test_no_jump_backwards_into_while_block(output): + i = 1 + while i <= 2: + output.append(3) + i += 1 + output.append(5) -def no_jump_backwards_into_block(output): - try: - for i in 1, 2: + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_with_block(output): + output.append(1) + with tracecontext(output, 2): output.append(3) - output.append(4) - except ValueError, e: - output.append('into' in str(e)) -no_jump_backwards_into_block.jump = (4, 3) -no_jump_backwards_into_block.output = [3, 3, True] + @jump_test(3, 2, [1, 2, -1], (ValueError, 'into')) + def test_no_jump_backwards_into_with_block(output): + with tracecontext(output, 1): + output.append(2) + output.append(3) -def no_jump_into_finally_block(output): - try: + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_try_finally_block(output): + output.append(1) try: output.append(3) - x = 1 finally: - output.append(6) - except ValueError, e: - output.append('finally' in str(e)) + output.append(5) -no_jump_into_finally_block.jump = (4, 6) -no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs + @jump_test(5, 2, [2, 4], (ValueError, 'into')) + def test_no_jump_backwards_into_try_finally_block(output): + try: + output.append(2) + finally: + output.append(4) + output.append(5) -def no_jump_out_of_finally_block(output): - try: + @jump_test(1, 3, [], (ValueError, 'into')) + def test_no_jump_forwards_into_try_except_block(output): + output.append(1) try: output.append(3) - finally: + except: output.append(5) - output.append(6) - except ValueError, e: - output.append('finally' in str(e)) + raise -no_jump_out_of_finally_block.jump = (5, 1) -no_jump_out_of_finally_block.output = [3, True] + @jump_test(6, 2, [2], (ValueError, 'into')) + def test_no_jump_backwards_into_try_except_block(output): + try: + output.append(2) + except: + output.append(4) + raise + output.append(6) -# This verifies the line-numbers-must-be-integers rule. -def no_jump_to_non_integers(output): - try: - output.append(2) - except ValueError, e: - output.append('integer' in str(e)) + @jump_test(3, 6, [2, 5, 6], (ValueError, 'finally')) + def test_no_jump_into_finally_block(output): + try: + output.append(2) + output.append(3) + finally: # still executed if the jump is failed + output.append(5) + output.append(6) + output.append(7) -no_jump_to_non_integers.jump = (2, "Spam") -no_jump_to_non_integers.output = [True] + @jump_test(1, 5, [], (ValueError, 'finally')) + def test_no_jump_into_finally_block_2(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) -def jump_across_with(output): - with open(test_support.TESTFN, "wb") as fp: - pass - with open(test_support.TESTFN, "wb") as fp: - pass -jump_across_with.jump = (1, 3) -jump_across_with.output = [] + @jump_test(5, 1, [1, 3], (ValueError, 'finally')) + def test_no_jump_out_of_finally_block(output): + output.append(1) + try: + output.append(3) + finally: + output.append(5) -# This verifies that you can't set f_lineno via _getframe or similar -# trickery. -def no_jump_without_trace_function(): - try: - previous_frame = sys._getframe().f_back - previous_frame.f_lineno = previous_frame.f_lineno - except ValueError, e: - # This is the exception we wanted; make sure the error message - # talks about trace functions. - if 'trace' not in str(e): - raise - else: - # Something's wrong - the expected exception wasn't raised. - raise RuntimeError, "Trace-function-less jump failed to fail" + @jump_test(2, 4, [1, 4, 5, -4]) + def test_jump_across_with(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) + with tracecontext(output, 4): + output.append(5) + @jump_test(3, 5, [1, 2, -2], (ValueError, 'into')) + def test_jump_across_with_2(output): + output.append(1) + with tracecontext(output, 2): + output.append(3) + with tracecontext(output, 4): + output.append(5) -class JumpTestCase(unittest.TestCase): - def compare_jump_output(self, expected, received): - if received != expected: - self.fail( "Outputs don't match:\n" + - "Expected: " + repr(expected) + "\n" + - "Received: " + repr(received)) + def test_no_jump_to_non_integers(self): + self.run_test(no_jump_to_non_integers, 2, "Spam", [True]) - def run_test(self, func): - tracer = JumpTracer(func) - sys.settrace(tracer.trace) - output = [] - func(output) - sys.settrace(None) - self.compare_jump_output(func.output, output) - - def test_01_jump_simple_forwards(self): - self.run_test(jump_simple_forwards) - def test_02_jump_simple_backwards(self): - self.run_test(jump_simple_backwards) - def test_03_jump_out_of_block_forwards(self): - self.run_test(jump_out_of_block_forwards) - def test_04_jump_out_of_block_backwards(self): - self.run_test(jump_out_of_block_backwards) - def test_05_jump_to_codeless_line(self): - self.run_test(jump_to_codeless_line) - def test_06_jump_to_same_line(self): - self.run_test(jump_to_same_line) - def test_07_jump_in_nested_finally(self): - self.run_test(jump_in_nested_finally) - def test_jump_infinite_while_loop(self): - self.run_test(jump_infinite_while_loop) - def test_08_no_jump_too_far_forwards(self): - self.run_test(no_jump_too_far_forwards) - def test_09_no_jump_too_far_backwards(self): - self.run_test(no_jump_too_far_backwards) - def test_10_no_jump_to_except_1(self): - self.run_test(no_jump_to_except_1) - def test_11_no_jump_to_except_2(self): - self.run_test(no_jump_to_except_2) - def test_12_no_jump_to_except_3(self): - self.run_test(no_jump_to_except_3) - def test_13_no_jump_to_except_4(self): - self.run_test(no_jump_to_except_4) - def test_14_no_jump_forwards_into_block(self): - self.run_test(no_jump_forwards_into_block) - def test_15_no_jump_backwards_into_block(self): - self.run_test(no_jump_backwards_into_block) - def test_16_no_jump_into_finally_block(self): - self.run_test(no_jump_into_finally_block) - def test_17_no_jump_out_of_finally_block(self): - self.run_test(no_jump_out_of_finally_block) - def test_18_no_jump_to_non_integers(self): - self.run_test(no_jump_to_non_integers) - def test_19_no_jump_without_trace_function(self): + def test_no_jump_without_trace_function(self): + # Must set sys.settrace(None) in setUp(), else condition is not + # triggered. no_jump_without_trace_function() - def test_jump_across_with(self): - self.addCleanup(test_support.unlink, test_support.TESTFN) - self.run_test(jump_across_with) - def test_20_large_function(self): + def test_large_function(self): d = {} exec("""def f(output): # line 0 x = 0 # line 1 @@ -783,10 +947,7 @@ def test_20_large_function(self): output.append(x) # line 1007 return""" % ('\n' * 1000,), d) f = d['f'] - - f.jump = (2, 1007) - f.output = [0] - self.run_test(f) + self.run_test(f, 2, 1007, [0]) def test_jump_to_firstlineno(self): # This tests that PDB can jump back to the first line in a @@ -800,8 +961,7 @@ def test_jump_to_firstlineno(self): """, "", "exec") class fake_function: func_code = code - jump = (2, 0) - tracer = JumpTracer(fake_function) + tracer = JumpTracer(fake_function, 2, 0) sys.settrace(tracer.trace) namespace = {"output": []} exec code in namespace From lp_benchmark_robot at intel.com Wed Dec 27 20:02:29 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 27 Dec 2017 17:02:29 -0800 Subject: [Python-checkins] [1 down, 4 up, 60 flat] Results for Python (master branch) 2017-12-27 Message-ID: Results for project python/master, build date: 2017-12-27 03:03:59-08:00. - commit: 53f9135 - previous commit: 62ed6be - revision date: 2017-12-27 00:38:56+02:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.855% | +0.692% | +5.680% | +7.254% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.156% | +0.063% | +23.576% | +5.609% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.629% | +0.037% | +25.609% | +3.573% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.144% | +0.957% | +22.975% | +5.019% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.551% | +1.182% | +8.529% | +8.595% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.421% | -0.607% | +9.411% | +13.646% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.744% | +0.258% | +5.837% | +11.890% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.558% | -1.363% | -1.879% | +9.357% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 2.649% | +0.758% | +10.661% | +17.442% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.726% | -2.147% | +11.943% | +13.842% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.092% | +0.740% | +3.774% | +7.389% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.981% | +0.820% | +5.190% | +4.930% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.717% | +0.442% | +2.018% | +8.465% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.004% | +0.334% | +12.691% | +10.615% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.270% | +1.209% | +9.783% | +9.500% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.703% | +0.976% | +6.319% | +11.572% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.649% | +0.401% | +10.236% | +10.356% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.502% | +1.218% | +6.931% | +10.329% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.380% | -1.422% | +2.568% | +10.321% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 2.844% | -1.807% | -0.655% | +13.967% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.825% | -1.510% | +6.065% | +13.410% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.705% | -0.858% | +46.565% | +12.965% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.686% | -1.100% | +7.425% | +15.040% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.574% | -0.087% | +16.777% | +12.645% | +-----+------------------------+--------+------------+------------+------------+ | :-) | mdp| 3.487% | +6.893% | +10.693% | +8.828% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 3.152% | +1.137% | +4.747% | +4.593% | +-----+------------------------+--------+------------+------------+------------+ | :-) | nbody| 0.694% | +4.298% | -0.746% | +0.858% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 2.376% | -0.523% | +4.035% | +7.387% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.309% | -1.509% | +2.074% | +12.014% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.375% | -0.194% | +1.477% | +20.178% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 6.344% | -3.561% | -1.505% | +22.103% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.766% | -0.476% | +2.706% | +20.881% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.023% | -1.136% | +10.524% | +11.022% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.050% | -0.017% | +0.122% | +10.168% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.150% | -0.612% | +10.328% | +5.757% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.099% | -0.572% | +1.739% | +5.565% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.875% | -1.129% | +9.326% | +13.610% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.039% | +4.124% | +5.635% | +9.865% | +-----+------------------------+--------+------------+------------+------------+ | :-( | regex_dna| 0.313% | -1.968% | -2.331% | +11.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.441% | -0.047% | -6.103% | +8.225% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.968% | -2.651% | +4.090% | +10.572% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.729% | -1.332% | +7.636% | +16.180% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.792% | +2.345% | -2.538% | +3.920% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.895% | +1.772% | +26.975% | +8.974% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.375% | -0.683% | +3.400% | +6.546% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.452% | +0.316% | +13.950% | +7.987% | +-----+------------------------+--------+------------+------------+------------+ | :-) | scimark_sparse_mat_mult| 0.565% | +3.641% | -3.592% | +2.520% | +-----+------------------------+--------+------------+------------+------------+ | :-) | spectral_norm| 0.429% | +3.071% | +5.518% | +3.342% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.238% | -0.073% | +6.380% | +7.193% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.063% | +0.611% | +6.792% | +3.569% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.075% | +2.414% | +21.270% | +6.360% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.306% | +0.208% | +12.067% | +5.915% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.135% | +0.023% | +9.226% | +6.698% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.317% | +1.141% | +12.348% | +8.096% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.031% | -0.018% | +11.051% | +8.758% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.319% | +3.243% | +19.899% | +11.306% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.881% | -0.363% | +6.058% | +6.846% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 2.545% | -1.084% | +1.478% | -1.199% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 5.328% | +5.394% | +9.561% | +18.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 4.246% | -3.844% | -7.059% | +17.591% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.422% | +1.258% | +8.209% | +6.406% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.107% | -0.663% | +1.669% | +12.431% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.625% | -0.983% | +2.022% | +9.496% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.535% | -3.783% | -10.251% | +15.163% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.337% | -0.058% | +4.113% | +11.439% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-down-4-up-60-flat-results-for-python-master-branch-2017-12-27 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu Dec 28 03:28:30 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 28 Dec 2017 08:28:30 -0000 Subject: [Python-checkins] Fix minor spelling error in test_sys_settrace.py. (#5025) Message-ID: https://github.com/python/cpython/commit/531dd7e27e6bbb89d66e507399bf3f9215bbb3e4 commit: 531dd7e27e6bbb89d66e507399bf3f9215bbb3e4 branch: master author: gfyoung committer: Serhiy Storchaka date: 2017-12-28T10:28:25+02:00 summary: Fix minor spelling error in test_sys_settrace.py. (#5025) files: M Lib/test/test_sys_settrace.py diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 4d88ae5fc2e..b4b578cc9dd 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -8,7 +8,7 @@ from functools import wraps class tracecontext: - """Contex manager that traces its enter and exit.""" + """Context manager that traces its enter and exit.""" def __init__(self, output, value): self.output = output self.value = value From solipsis at pitrou.net Thu Dec 28 04:15:41 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 28 Dec 2017 09:15:41 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=5 Message-ID: <20171228091541.1.7EB595254452F6E1@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, -2, 0] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogrKFCmm', '--timeout', '7200'] From webhook-mailer at python.org Thu Dec 28 09:37:50 2017 From: webhook-mailer at python.org (Mariatta) Date: Thu, 28 Dec 2017 14:37:50 -0000 Subject: [Python-checkins] bpo-32440: Update the docs URL to https in help() (GH-5030) Message-ID: https://github.com/python/cpython/commit/e5681b9822c633c77ddfeb94585d58895e0ecff5 commit: e5681b9822c633c77ddfeb94585d58895e0ecff5 branch: master author: oldk committer: Mariatta date: 2017-12-28T06:37:46-08:00 summary: bpo-32440: Update the docs URL to https in help() (GH-5030) In pydoc.py, the reference to Python' documentation was in http. The link has been updated to use https. files: M Lib/pydoc.py diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 01f7a32f454..7d0b1d8aefb 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1952,7 +1952,7 @@ def intro(self): Welcome to Python {0}'s help utility! If this is your first time using Python, you should definitely check out -the tutorial on the Internet at http://docs.python.org/{0}/tutorial/. +the tutorial on the Internet at https://docs.python.org/{0}/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and From webhook-mailer at python.org Thu Dec 28 10:16:42 2017 From: webhook-mailer at python.org (Mariatta) Date: Thu, 28 Dec 2017 15:16:42 -0000 Subject: [Python-checkins] bpo-32440: Update the docs URL to https in help() (GH-5030) (GH-5031) Message-ID: https://github.com/python/cpython/commit/6eb232c52a03e31fc47842e70fc7833198744c2b commit: 6eb232c52a03e31fc47842e70fc7833198744c2b branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2017-12-28T07:16:39-08:00 summary: bpo-32440: Update the docs URL to https in help() (GH-5030) (GH-5031) In pydoc.py, the reference to Python' documentation was in http. The link has been updated to use https. (cherry picked from commit e5681b9822c633c77ddfeb94585d58895e0ecff5) files: M Lib/pydoc.py diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 39db3915dc2..34e2fabf20e 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1916,7 +1916,7 @@ def intro(self): Welcome to Python {0}'s help utility! If this is your first time using Python, you should definitely check out -the tutorial on the Internet at http://docs.python.org/{0}/tutorial/. +the tutorial on the Internet at https://docs.python.org/{0}/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and From lp_benchmark_robot at intel.com Thu Dec 28 19:35:23 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 28 Dec 2017 16:35:23 -0800 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2017-12-28 Message-ID: <6f2b6313-1e02-4a09-8b91-4ca857bbff27@orsmsx154.amr.corp.intel.com> Results for project python/master, build date: 2017-12-28 03:04:02-08:00. - commit: 531dd7e - previous commit: 53f9135 - revision date: 2017-12-28 10:28:25+02:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.929% | +0.011% | +5.690% | +7.484% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.515% | +0.278% | +23.788% | +9.742% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.864% | -0.246% | +25.426% | +8.562% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.713% | +0.261% | +23.176% | +8.842% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.395% | +0.270% | +8.776% | +5.837% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.641% | -0.072% | +9.346% | +12.502% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.108% | -0.201% | +5.648% | +11.594% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.750% | +0.032% | -1.847% | +9.758% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 2.949% | -0.295% | +10.397% | +16.631% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.651% | +0.925% | +12.758% | +13.767% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.591% | +0.011% | +3.784% | +7.680% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.523% | +0.138% | +5.320% | +3.876% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 2.729% | -0.970% | +1.068% | +8.568% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.087% | +0.322% | +12.972% | +9.488% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.636% | -0.552% | +9.285% | +8.663% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.841% | -0.240% | +6.094% | +11.284% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.551% | -0.105% | +10.141% | +10.587% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.483% | +0.460% | +7.359% | +10.626% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.438% | +0.809% | +3.356% | +7.978% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 1.854% | +0.600% | -0.051% | +12.856% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.324% | +1.008% | +7.012% | +13.268% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.964% | -0.275% | +46.418% | +13.772% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.600% | -0.296% | +7.151% | +14.882% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 1.075% | -0.332% | +16.501% | +13.653% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 4.188% | +0.030% | +10.720% | +8.852% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 3.291% | +0.317% | +5.049% | +3.937% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.978% | +0.025% | -0.721% | +0.133% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 1.390% | +0.198% | +4.225% | +7.524% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.254% | +1.124% | +3.174% | +12.159% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.147% | -0.622% | +0.864% | +20.776% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.471% | +1.096% | -0.392% | +22.450% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.789% | -0.130% | +2.579% | +21.905% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 2.448% | +0.244% | +10.742% | +10.218% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.176% | -0.039% | +0.083% | +9.968% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.147% | +0.226% | +10.531% | +5.413% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.117% | +0.218% | +1.953% | +5.385% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.586% | +0.335% | +9.629% | +14.489% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.103% | -0.408% | +5.250% | +9.149% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.447% | -0.052% | -2.383% | +11.585% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.542% | -0.246% | -6.364% | +7.551% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.389% | +0.258% | +4.338% | +9.336% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.303% | +0.750% | +8.329% | +14.483% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.519% | +0.236% | -2.296% | +2.164% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.722% | +0.227% | +27.141% | +7.993% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.899% | +0.636% | +4.014% | +6.317% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.101% | +0.083% | +14.022% | +9.200% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.547% | +0.161% | -3.426% | +0.147% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.400% | +0.030% | +5.547% | +2.307% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.074% | +0.229% | +6.595% | +7.131% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 2.886% | -0.029% | +6.765% | +4.172% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 5.023% | -3.726% | +18.337% | +8.798% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.721% | +0.113% | +12.166% | +5.693% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.067% | -0.336% | +8.921% | +6.891% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.655% | +0.064% | +12.405% | +7.583% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.295% | -0.724% | +10.408% | +10.477% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 5.623% | -1.300% | +18.858% | +10.484% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.223% | -0.019% | +6.040% | +6.692% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 2.175% | +0.064% | +1.541% | +2.325% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.619% | -1.714% | +8.011% | +18.642% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 3.659% | +0.250% | -6.791% | +19.868% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 0.937% | -0.022% | +8.188% | +6.421% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.904% | +0.579% | +2.238% | +12.091% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.739% | +0.926% | +2.930% | +8.017% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.651% | -0.315% | -10.598% | +14.659% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.397% | +0.224% | +4.328% | +11.394% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2017-12-28 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu Dec 28 20:54:14 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 29 Dec 2017 01:54:14 -0000 Subject: [Python-checkins] make PatternCompiler use the packaged grammar if possible (more bpo-24960) (#5034) Message-ID: https://github.com/python/cpython/commit/e5f7dccefaa8d97ab53b3051acbb4a4d49379dc4 commit: e5f7dccefaa8d97ab53b3051acbb4a4d49379dc4 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-28T17:54:12-08:00 summary: make PatternCompiler use the packaged grammar if possible (more bpo-24960) (#5034) files: M Lib/lib2to3/patcomp.py diff --git a/Lib/lib2to3/patcomp.py b/Lib/lib2to3/patcomp.py index 0fefa9a3a42..4e79ed26923 100644 --- a/Lib/lib2to3/patcomp.py +++ b/Lib/lib2to3/patcomp.py @@ -21,10 +21,6 @@ from . import pytree from . import pygram -# The pattern grammar file -_PATTERN_GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), - "PatternGrammar.txt") - class PatternSyntaxError(Exception): pass @@ -42,13 +38,17 @@ def tokenize_wrapper(input): class PatternCompiler(object): - def __init__(self, grammar_file=_PATTERN_GRAMMAR_FILE): + def __init__(self, grammar_file=None): """Initializer. Takes an optional alternative filename for the pattern grammar. """ - self.grammar = driver.load_grammar(grammar_file) - self.syms = pygram.Symbols(self.grammar) + if grammar_file is None: + self.grammar = pygram.pattern_grammar + self.syms = pygram.pattern_symbols + else: + self.grammar = driver.load_grammar(grammar_file) + self.syms = pygram.Symbols(self.grammar) self.pygrammar = pygram.python_grammar self.pysyms = pygram.python_symbols self.driver = driver.Driver(self.grammar, convert=pattern_convert) From webhook-mailer at python.org Thu Dec 28 21:05:10 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 29 Dec 2017 02:05:10 -0000 Subject: [Python-checkins] make PatternCompiler use the packaged grammar if possible (more bpo-24960) (GH-5034) (#5037) Message-ID: https://github.com/python/cpython/commit/417f76a20e93044e422fb328a2d8e200fc6df295 commit: 417f76a20e93044e422fb328a2d8e200fc6df295 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2017-12-28T18:05:07-08:00 summary: make PatternCompiler use the packaged grammar if possible (more bpo-24960) (GH-5034) (#5037) (cherry picked from commit e5f7dccefaa8d97ab53b3051acbb4a4d49379dc4) files: M Lib/lib2to3/patcomp.py diff --git a/Lib/lib2to3/patcomp.py b/Lib/lib2to3/patcomp.py index d31a9dad9a5..00679b2238e 100644 --- a/Lib/lib2to3/patcomp.py +++ b/Lib/lib2to3/patcomp.py @@ -21,10 +21,6 @@ from . import pytree from . import pygram -# The pattern grammar file -_PATTERN_GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), - "PatternGrammar.txt") - class PatternSyntaxError(Exception): pass @@ -42,13 +38,17 @@ def tokenize_wrapper(input): class PatternCompiler(object): - def __init__(self, grammar_file=_PATTERN_GRAMMAR_FILE): + def __init__(self, grammar_file=None): """Initializer. Takes an optional alternative filename for the pattern grammar. """ - self.grammar = driver.load_grammar(grammar_file) - self.syms = pygram.Symbols(self.grammar) + if grammar_file is None: + self.grammar = pygram.pattern_grammar + self.syms = pygram.pattern_symbols + else: + self.grammar = driver.load_grammar(grammar_file) + self.syms = pygram.Symbols(self.grammar) self.pygrammar = pygram.python_grammar self.pysyms = pygram.python_symbols self.driver = driver.Driver(self.grammar, convert=pattern_convert) From webhook-mailer at python.org Thu Dec 28 21:12:43 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 29 Dec 2017 02:12:43 -0000 Subject: [Python-checkins] make PatternCompiler use the packaged grammar if possible (more bpo-24960) (GH-5034) (#5036) Message-ID: https://github.com/python/cpython/commit/85f71aa9d6f834c7d64e979009c8fda0f19b585d commit: 85f71aa9d6f834c7d64e979009c8fda0f19b585d branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2017-12-28T18:12:41-08:00 summary: make PatternCompiler use the packaged grammar if possible (more bpo-24960) (GH-5034) (#5036) (cherry picked from commit e5f7dccefaa8d97ab53b3051acbb4a4d49379dc4) files: M Lib/lib2to3/patcomp.py diff --git a/Lib/lib2to3/patcomp.py b/Lib/lib2to3/patcomp.py index 06a4b9dd230..5bda0f9299d 100644 --- a/Lib/lib2to3/patcomp.py +++ b/Lib/lib2to3/patcomp.py @@ -21,10 +21,6 @@ from . import pytree from . import pygram -# The pattern grammar file -_PATTERN_GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), - "PatternGrammar.txt") - class PatternSyntaxError(Exception): pass @@ -42,13 +38,17 @@ def tokenize_wrapper(input): class PatternCompiler(object): - def __init__(self, grammar_file=_PATTERN_GRAMMAR_FILE): + def __init__(self, grammar_file=None): """Initializer. Takes an optional alternative filename for the pattern grammar. """ - self.grammar = driver.load_grammar(grammar_file) - self.syms = pygram.Symbols(self.grammar) + if grammar_file is None: + self.grammar = pygram.pattern_grammar + self.syms = pygram.pattern_symbols + else: + self.grammar = driver.load_grammar(grammar_file) + self.syms = pygram.Symbols(self.grammar) self.pygrammar = pygram.python_grammar self.pysyms = pygram.python_symbols self.driver = driver.Driver(self.grammar, convert=pattern_convert) From webhook-mailer at python.org Fri Dec 29 02:24:43 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 29 Dec 2017 07:24:43 -0000 Subject: [Python-checkins] remove unused import (#5040) Message-ID: https://github.com/python/cpython/commit/e325608740bee161ca7fefd09463d63099efa1b8 commit: e325608740bee161ca7fefd09463d63099efa1b8 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-28T23:24:40-08:00 summary: remove unused import (#5040) files: M Lib/lib2to3/patcomp.py diff --git a/Lib/lib2to3/patcomp.py b/Lib/lib2to3/patcomp.py index 4e79ed26923..f57f4954b26 100644 --- a/Lib/lib2to3/patcomp.py +++ b/Lib/lib2to3/patcomp.py @@ -12,7 +12,6 @@ # Python imports import io -import os # Fairly local imports from .pgen2 import driver, literals, token, tokenize, parse, grammar From webhook-mailer at python.org Fri Dec 29 02:38:58 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 29 Dec 2017 07:38:58 -0000 Subject: [Python-checkins] [2.7] remove unused import (GH-5040). (#5043) Message-ID: https://github.com/python/cpython/commit/1f9d549a3bba9c87ee9571e329c20f3056f446db commit: 1f9d549a3bba9c87ee9571e329c20f3056f446db branch: 2.7 author: Benjamin Peterson committer: GitHub date: 2017-12-28T23:38:55-08:00 summary: [2.7] remove unused import (GH-5040). (#5043) (cherry picked from commit e325608740bee161ca7fefd09463d63099efa1b8) files: M Lib/lib2to3/patcomp.py diff --git a/Lib/lib2to3/patcomp.py b/Lib/lib2to3/patcomp.py index 00679b2238e..49ed6680b6a 100644 --- a/Lib/lib2to3/patcomp.py +++ b/Lib/lib2to3/patcomp.py @@ -11,7 +11,6 @@ __author__ = "Guido van Rossum " # Python imports -import os import StringIO # Fairly local imports From webhook-mailer at python.org Fri Dec 29 02:48:13 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 29 Dec 2017 07:48:13 -0000 Subject: [Python-checkins] remove unused import (GH-5040) (#5042) Message-ID: https://github.com/python/cpython/commit/1b2812a7b49771b3c6918f29ac2a2678d80c74f3 commit: 1b2812a7b49771b3c6918f29ac2a2678d80c74f3 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2017-12-28T23:48:10-08:00 summary: remove unused import (GH-5040) (#5042) (cherry picked from commit e325608740bee161ca7fefd09463d63099efa1b8) files: M Lib/lib2to3/patcomp.py diff --git a/Lib/lib2to3/patcomp.py b/Lib/lib2to3/patcomp.py index 5bda0f9299d..f6f845e3608 100644 --- a/Lib/lib2to3/patcomp.py +++ b/Lib/lib2to3/patcomp.py @@ -12,7 +12,6 @@ # Python imports import io -import os # Fairly local imports from .pgen2 import driver, literals, token, tokenize, parse, grammar From solipsis at pitrou.net Fri Dec 29 04:18:40 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 29 Dec 2017 09:18:40 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=12 Message-ID: <20171229091840.1.FDA9BBD893B9B9B1@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, 0] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [1, -2, 2] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogL0NAO5', '--timeout', '7200'] From webhook-mailer at python.org Fri Dec 29 14:00:01 2017 From: webhook-mailer at python.org (Eric V. Smith) Date: Fri, 29 Dec 2017 19:00:01 -0000 Subject: [Python-checkins] bpo-32427: Expose dataclasses.MISSING object. (#5045) Message-ID: https://github.com/python/cpython/commit/03220fdb26c0b6a50ce5ed1fdfbf232094b66db6 commit: 03220fdb26c0b6a50ce5ed1fdfbf232094b66db6 branch: master author: Eric V. Smith committer: GitHub date: 2017-12-29T13:59:58-05:00 summary: bpo-32427: Expose dataclasses.MISSING object. (#5045) files: M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 7a725dfb520..eaaed63ef28 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -8,6 +8,7 @@ 'field', 'FrozenInstanceError', 'InitVar', + 'MISSING', # Helper functions. 'fields', @@ -29,11 +30,11 @@ def __repr__(self): return '' _HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS() -# A sentinel object to detect if a parameter is supplied or not. -class _MISSING_FACTORY: - def __repr__(self): - return '' -_MISSING = _MISSING_FACTORY() +# A sentinel object to detect if a parameter is supplied or not. Use +# a class to give it a better repr. +class _MISSING_TYPE: + pass +MISSING = _MISSING_TYPE() # Since most per-field metadata will be unused, create an empty # read-only proxy that can be shared among all fields. @@ -114,7 +115,7 @@ def __repr__(self): # This function is used instead of exposing Field creation directly, # so that a type checker can be told (via overloads) that this is a # function whose type depends on its parameters. -def field(*, default=_MISSING, default_factory=_MISSING, init=True, repr=True, +def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None): """Return an object to identify dataclass fields. @@ -130,7 +131,7 @@ def field(*, default=_MISSING, default_factory=_MISSING, init=True, repr=True, It is an error to specify both default and default_factory. """ - if default is not _MISSING and default_factory is not _MISSING: + if default is not MISSING and default_factory is not MISSING: raise ValueError('cannot specify both default and default_factory') return Field(default, default_factory, init, repr, hash, compare, metadata) @@ -149,12 +150,12 @@ def _tuple_str(obj_name, fields): def _create_fn(name, args, body, globals=None, locals=None, - return_type=_MISSING): + return_type=MISSING): # Note that we mutate locals when exec() is called. Caller beware! if locals is None: locals = {} return_annotation = '' - if return_type is not _MISSING: + if return_type is not MISSING: locals['_return_type'] = return_type return_annotation = '->_return_type' args = ','.join(args) @@ -182,7 +183,7 @@ def _field_init(f, frozen, globals, self_name): # initialize this field. default_name = f'_dflt_{f.name}' - if f.default_factory is not _MISSING: + if f.default_factory is not MISSING: if f.init: # This field has a default factory. If a parameter is # given, use it. If not, call the factory. @@ -210,10 +211,10 @@ def _field_init(f, frozen, globals, self_name): else: # No default factory. if f.init: - if f.default is _MISSING: + if f.default is MISSING: # There's no default, just do an assignment. value = f.name - elif f.default is not _MISSING: + elif f.default is not MISSING: globals[default_name] = f.default value = f.name else: @@ -236,14 +237,14 @@ def _init_param(f): # For example, the equivalent of 'x:int=3' (except instead of 'int', # reference a variable set to int, and instead of '3', reference a # variable set to 3). - if f.default is _MISSING and f.default_factory is _MISSING: + if f.default is MISSING and f.default_factory is MISSING: # There's no default, and no default_factory, just # output the variable name and type. default = '' - elif f.default is not _MISSING: + elif f.default is not MISSING: # There's a default, this will be the name that's used to look it up. default = f'=_dflt_{f.name}' - elif f.default_factory is not _MISSING: + elif f.default_factory is not MISSING: # There's a factory function. Set a marker. default = '=_HAS_DEFAULT_FACTORY' return f'{f.name}:_type_{f.name}{default}' @@ -261,13 +262,13 @@ def _init_fn(fields, frozen, has_post_init, self_name): for f in fields: # Only consider fields in the __init__ call. if f.init: - if not (f.default is _MISSING and f.default_factory is _MISSING): + if not (f.default is MISSING and f.default_factory is MISSING): seen_default = True elif seen_default: raise TypeError(f'non-default argument {f.name!r} ' 'follows default argument') - globals = {'_MISSING': _MISSING, + globals = {'MISSING': MISSING, '_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY} body_lines = [] @@ -368,7 +369,7 @@ def _get_field(cls, a_name, a_type): # If the default value isn't derived from field, then it's # only a normal default value. Convert it to a Field(). - default = getattr(cls, a_name, _MISSING) + default = getattr(cls, a_name, MISSING) if isinstance(default, Field): f = default else: @@ -404,7 +405,7 @@ def _get_field(cls, a_name, a_type): # Special restrictions for ClassVar and InitVar. if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR): - if f.default_factory is not _MISSING: + if f.default_factory is not MISSING: raise TypeError(f'field {f.name} cannot have a ' 'default factory') # Should I check for other field settings? default_factory @@ -474,7 +475,7 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): # with the real default. This is so that normal class # introspection sees a real default value, not a Field. if isinstance(getattr(cls, f.name, None), Field): - if f.default is _MISSING: + if f.default is MISSING: # If there's no default, delete the class attribute. # This happens if we specify field(repr=False), for # example (that is, we specified a field object, but diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 7fbea76ccd8..ed695639882 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1,6 +1,6 @@ from dataclasses import ( dataclass, field, FrozenInstanceError, fields, asdict, astuple, - make_dataclass, replace, InitVar, Field + make_dataclass, replace, InitVar, Field, MISSING ) import pickle @@ -917,12 +917,12 @@ def validate_class(cls): param = next(params) self.assertEqual(param.name, 'k') self.assertIs (param.annotation, F) - # Don't test for the default, since it's set to _MISSING + # Don't test for the default, since it's set to MISSING self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) param = next(params) self.assertEqual(param.name, 'l') self.assertIs (param.annotation, float) - # Don't test for the default, since it's set to _MISSING + # Don't test for the default, since it's set to MISSING self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) self.assertRaises(StopIteration, next, params) @@ -948,6 +948,52 @@ class C: validate_class(C) + def test_missing_default(self): + # Test that MISSING works the same as a default not being + # specified. + @dataclass + class C: + x: int=field(default=MISSING) + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + C() + self.assertNotIn('x', C.__dict__) + + @dataclass + class D: + x: int + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + D() + self.assertNotIn('x', D.__dict__) + + def test_missing_default_factory(self): + # Test that MISSING works the same as a default factory not + # being specified (which is really the same as a default not + # being specified, too). + @dataclass + class C: + x: int=field(default_factory=MISSING) + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + C() + self.assertNotIn('x', C.__dict__) + + @dataclass + class D: + x: int=field(default=MISSING, default_factory=MISSING) + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + D() + self.assertNotIn('x', D.__dict__) + + def test_missing_repr(self): + self.assertIn('MISSING_TYPE object', repr(MISSING)) + def test_dont_include_other_annotations(self): @dataclass class C: From webhook-mailer at python.org Fri Dec 29 15:44:09 2017 From: webhook-mailer at python.org (Gregory P. Smith) Date: Fri, 29 Dec 2017 20:44:09 -0000 Subject: [Python-checkins] bpo-18035: telnetlib: select.error doesn't have an errno attribute (#5044) Message-ID: https://github.com/python/cpython/commit/3ceaed0dce81fd881bbaf2dbdbe827d9681887da commit: 3ceaed0dce81fd881bbaf2dbdbe827d9681887da branch: 2.7 author: Segev Finer committer: Gregory P. Smith date: 2017-12-29T12:44:04-08:00 summary: bpo-18035: telnetlib: select.error doesn't have an errno attribute (#5044) select.error doesn't have an errno attribute so access the errno by indexing instead. files: A Misc/NEWS.d/next/Library/2017-12-29-15-16-56.bpo-18035.c6rdCt.rst M Lib/telnetlib.py diff --git a/Lib/telnetlib.py b/Lib/telnetlib.py index 2eaa8e37098..d0246c0aea7 100644 --- a/Lib/telnetlib.py +++ b/Lib/telnetlib.py @@ -317,7 +317,7 @@ def _read_until_with_poll(self, match, timeout): ready = poller.poll(None if timeout is None else 1000 * call_timeout) except select.error as e: - if e.errno == errno.EINTR: + if e[0] == errno.EINTR: if timeout is not None: elapsed = time() - time_start call_timeout = timeout-elapsed @@ -688,7 +688,7 @@ def _expect_with_poll(self, expect_list, timeout=None): ready = poller.poll(None if timeout is None else 1000 * call_timeout) except select.error as e: - if e.errno == errno.EINTR: + if e[0] == errno.EINTR: if timeout is not None: elapsed = time() - time_start call_timeout = timeout-elapsed diff --git a/Misc/NEWS.d/next/Library/2017-12-29-15-16-56.bpo-18035.c6rdCt.rst b/Misc/NEWS.d/next/Library/2017-12-29-15-16-56.bpo-18035.c6rdCt.rst new file mode 100644 index 00000000000..7b6e0dc6b28 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-29-15-16-56.bpo-18035.c6rdCt.rst @@ -0,0 +1,2 @@ +``telnetlib``: ``select.error`` doesn't have an ``errno`` attribute. Patch +by Segev Finer. From webhook-mailer at python.org Fri Dec 29 16:13:09 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Fri, 29 Dec 2017 21:13:09 -0000 Subject: [Python-checkins] return the new file descriptor from os.dup2 (closes bpo-32441) (#5041) Message-ID: https://github.com/python/cpython/commit/bbdb17d19bb1d5443ca4417254e014ad64c04540 commit: bbdb17d19bb1d5443ca4417254e014ad64c04540 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-29T13:13:06-08:00 summary: return the new file descriptor from os.dup2 (closes bpo-32441) (#5041) files: A Misc/NEWS.d/next/Library/2017-12-28-21-30-40.bpo-32441.LqlboJ.rst M Doc/library/os.rst M Lib/test/test_os.py M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c diff --git a/Doc/library/os.rst b/Doc/library/os.rst index a24934ceb7b..ee08853087f 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -735,13 +735,17 @@ as internal buffering of data. .. function:: dup2(fd, fd2, inheritable=True) - Duplicate file descriptor *fd* to *fd2*, closing the latter first if necessary. - The file descriptor *fd2* is :ref:`inheritable ` by default, - or non-inheritable if *inheritable* is ``False``. + Duplicate file descriptor *fd* to *fd2*, closing the latter first if + necessary. Return *fd2*. The new file descriptor is :ref:`inheritable + ` by default or non-inheritable if *inheritable* + is ``False``. .. versionchanged:: 3.4 Add the optional *inheritable* parameter. + .. versionchanged:: 3.7 + Return *fd2* on success. Previously, ``None`` was always returned. + .. function:: fchmod(fd, mode) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index f235f801e03..83e214d91ea 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3079,19 +3079,15 @@ def test_dup2(self): # inheritable by default fd2 = os.open(__file__, os.O_RDONLY) - try: - os.dup2(fd, fd2) - self.assertEqual(os.get_inheritable(fd2), True) - finally: - os.close(fd2) + self.addCleanup(os.close, fd2) + self.assertEqual(os.dup2(fd, fd2), fd2) + self.assertTrue(os.get_inheritable(fd2)) # force non-inheritable fd3 = os.open(__file__, os.O_RDONLY) - try: - os.dup2(fd, fd3, inheritable=False) - self.assertEqual(os.get_inheritable(fd3), False) - finally: - os.close(fd3) + self.addCleanup(os.close, fd3) + self.assertEqual(os.dup2(fd, fd3, inheritable=False), fd3) + self.assertFalse(os.get_inheritable(fd3)) @unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()") def test_openpty(self): diff --git a/Misc/NEWS.d/next/Library/2017-12-28-21-30-40.bpo-32441.LqlboJ.rst b/Misc/NEWS.d/next/Library/2017-12-28-21-30-40.bpo-32441.LqlboJ.rst new file mode 100644 index 00000000000..a0fe4f3cc6c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-28-21-30-40.bpo-32441.LqlboJ.rst @@ -0,0 +1,2 @@ +Return the new file descriptor (i.e., the second argument) from ``os.dup2``. +Previously, ``None`` was always returned. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 9decf7a8d24..6f4c028e7ef 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -3486,7 +3486,7 @@ PyDoc_STRVAR(os_dup2__doc__, #define OS_DUP2_METHODDEF \ {"dup2", (PyCFunction)os_dup2, METH_FASTCALL|METH_KEYWORDS, os_dup2__doc__}, -static PyObject * +static int os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable); static PyObject * @@ -3498,12 +3498,17 @@ os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn int fd; int fd2; int inheritable = 1; + int _return_value; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, &fd, &fd2, &inheritable)) { goto exit; } - return_value = os_dup2_impl(module, fd, fd2, inheritable); + _return_value = os_dup2_impl(module, fd, fd2, inheritable); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); exit: return return_value; @@ -6405,4 +6410,4 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=b6ade5f170d5a431 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6345053cd5992caf input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 38b6c80e6bd..47b79fcc798 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7770,7 +7770,7 @@ os_dup_impl(PyObject *module, int fd) /*[clinic input] -os.dup2 +os.dup2 -> int fd: int fd2: int inheritable: bool=True @@ -7778,9 +7778,9 @@ os.dup2 Duplicate file descriptor. [clinic start generated code]*/ -static PyObject * +static int os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) -/*[clinic end generated code: output=db832a2d872ccc5f input=76e96f511be0352f]*/ +/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/ { int res; #if defined(HAVE_DUP3) && \ @@ -7789,8 +7789,10 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) int dup3_works = -1; #endif - if (fd < 0 || fd2 < 0) - return posix_error(); + if (fd < 0 || fd2 < 0) { + posix_error(); + return -1; + } /* dup2() can fail with EINTR if the target FD is already open, because it * then has to be closed. See os_close_impl() for why we don't handle EINTR @@ -7802,13 +7804,16 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) res = dup2(fd, fd2); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); + if (res < 0) { + posix_error(); + return -1; + } + res = fd2; // msvcrt dup2 returns 0 on success. /* Character files like console cannot be make non-inheritable */ if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { close(fd2); - return NULL; + return -1; } #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) @@ -7818,8 +7823,10 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) else res = dup2(fd, fd2); Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); + if (res < 0) { + posix_error(); + return -1; + } #else @@ -7831,8 +7838,10 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) if (res < 0) { if (dup3_works == -1) dup3_works = (errno != ENOSYS); - if (dup3_works) - return posix_error(); + if (dup3_works) { + posix_error(); + return -1; + } } } @@ -7842,12 +7851,14 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) Py_BEGIN_ALLOW_THREADS res = dup2(fd, fd2); Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); + if (res < 0) { + posix_error(); + return -1; + } if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { close(fd2); - return NULL; + return -1; } #ifdef HAVE_DUP3 } @@ -7855,7 +7866,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) #endif - Py_RETURN_NONE; + return res; } From lp_benchmark_robot at intel.com Fri Dec 29 19:08:05 2017 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 29 Dec 2017 16:08:05 -0800 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2017-12-29 Message-ID: Results for project python/master, build date: 2017-12-29 03:03:56-08:00. - commit: e325608 - previous commit: 531dd7e - revision date: 2017-12-28 23:24:40-08:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 1.095% | +1.615% | +7.213% | +7.126% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.604% | -0.079% | +23.728% | +9.367% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.817% | +0.146% | +25.534% | +4.980% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.046% | -0.314% | +22.935% | +7.907% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.059% | -0.160% | +8.631% | +9.215% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.300% | +0.336% | +9.651% | +13.793% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.819% | +0.061% | +5.705% | +10.983% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.595% | +0.205% | -1.638% | +9.368% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 2.746% | +0.352% | +10.712% | +14.661% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.297% | -0.742% | +12.110% | +15.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.247% | -0.021% | +3.764% | +7.901% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.573% | -0.053% | +5.270% | +4.439% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 0.727% | +0.894% | +1.952% | +6.033% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.027% | -0.172% | +12.822% | +10.568% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.198% | -0.526% | +8.808% | +10.690% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 0.885% | +0.227% | +6.307% | +9.599% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.512% | +0.114% | +10.244% | +10.741% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.204% | -0.632% | +6.773% | +9.246% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.160% | +0.358% | +3.702% | +8.373% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 1.289% | +0.225% | +0.174% | +12.734% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.390% | -0.886% | +6.188% | +12.669% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.664% | +0.678% | +46.781% | +13.070% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.848% | -0.707% | +6.494% | +14.858% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.801% | +0.202% | +16.669% | +11.837% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 4.374% | +0.055% | +10.769% | +8.965% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 3.534% | +0.067% | +5.112% | +4.621% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.636% | +0.065% | -0.656% | -3.768% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 1.900% | +0.136% | +4.355% | +7.598% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.081% | -0.398% | +2.789% | +11.552% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 4.335% | -0.520% | +0.348% | +21.615% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.612% | -0.228% | -0.621% | +23.883% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.821% | +0.019% | +2.598% | +21.242% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.639% | -0.561% | +10.241% | +10.595% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.220% | -0.051% | +0.033% | +9.805% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.155% | -0.068% | +10.470% | +5.402% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.114% | +0.020% | +1.973% | +5.281% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.105% | +0.219% | +9.827% | +11.455% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.363% | +0.793% | +6.001% | +9.442% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.309% | +0.113% | -2.268% | +11.512% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.999% | +0.056% | -6.304% | +7.167% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.479% | +0.110% | +4.443% | +9.675% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.680% | -0.477% | +7.892% | +14.757% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.804% | -0.185% | -2.485% | +3.068% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 1.714% | -0.215% | +26.984% | +7.575% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.887% | +0.508% | +4.502% | +2.725% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.773% | +0.306% | +14.285% | +6.156% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.876% | -0.211% | -3.643% | -4.259% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.498% | -0.115% | +5.438% | +2.880% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.236% | -0.059% | +6.540% | +5.889% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.639% | -0.970% | +5.860% | +3.119% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.822% | +2.196% | +20.130% | +8.135% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.070% | -0.147% | +12.036% | +6.033% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.065% | +0.172% | +9.077% | +6.338% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.162% | -0.674% | +11.814% | +9.108% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.240% | +0.335% | +10.708% | +9.106% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 5.917% | +0.383% | +19.169% | +12.553% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.010% | +0.086% | +6.121% | +6.395% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.773% | +0.167% | +1.705% | +0.426% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 5.614% | +1.505% | +9.395% | +20.774% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 5.356% | -0.049% | -6.843% | +18.757% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.450% | -0.255% | +7.954% | +6.904% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.302% | -0.390% | +1.857% | +12.728% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.484% | -0.391% | +2.550% | +8.039% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.415% | -0.326% | -10.958% | +15.123% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.363% | -0.053% | +4.277% | +12.013% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2017-12-29 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Sat Dec 30 00:35:39 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 30 Dec 2017 05:35:39 -0000 Subject: [Python-checkins] bpo-23749: Implement loop.start_tls() (#5039) Message-ID: https://github.com/python/cpython/commit/f111b3dcb414093a4efb9d74b69925e535ddc470 commit: f111b3dcb414093a4efb9d74b69925e535ddc470 branch: master author: Yury Selivanov committer: GitHub date: 2017-12-30T00:35:36-05:00 summary: bpo-23749: Implement loop.start_tls() (#5039) files: A Lib/test/test_asyncio/functional.py A Misc/NEWS.d/next/Library/2017-12-29-00-44-42.bpo-23749.QL1Cxd.rst M Doc/library/asyncio-eventloop.rst M Lib/asyncio/base_events.py M Lib/asyncio/events.py M Lib/asyncio/proactor_events.py M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_sslproto.py M Lib/test/test_asyncio/utils.py diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 5dd258df312..33b86d6f033 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -537,6 +537,38 @@ Creating listening connections .. versionadded:: 3.5.3 +TLS Upgrade +----------- + +.. coroutinemethod:: AbstractEventLoop.start_tls(transport, protocol, sslcontext, \*, server_side=False, server_hostname=None, ssl_handshake_timeout=None) + + Upgrades an existing connection to TLS. + + Returns a new transport instance, that the *protocol* must start using + immediately after the *await*. The *transport* instance passed to + the *start_tls* method should never be used again. + + Parameters: + + * *transport* and *protocol* instances that methods like + :meth:`~AbstractEventLoop.create_server` and + :meth:`~AbstractEventLoop.create_connection` return. + + * *sslcontext*: a configured instance of :class:`~ssl.SSLContext`. + + * *server_side* pass ``True`` when a server-side connection is being + upgraded (like the one created by :meth:`~AbstractEventLoop.create_server`). + + * *server_hostname*: sets or overrides the host name that the target + server's certificate will be matched against. + + * *ssl_handshake_timeout* is (for an SSL connection) the time in seconds to + wait for the SSL handshake to complete before aborting the connection. + ``10.0`` seconds if ``None`` (default). + + .. versionadded:: 3.7 + + Watch file descriptors ---------------------- diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 96cc4f02588..00831b39853 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -29,9 +29,15 @@ import warnings import weakref +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + from . import coroutines from . import events from . import futures +from . import sslproto from . import tasks from .log import logger @@ -279,7 +285,8 @@ def _make_ssl_transport( self, rawsock, protocol, sslcontext, waiter=None, *, server_side=False, server_hostname=None, extra=None, server=None, - ssl_handshake_timeout=None): + ssl_handshake_timeout=None, + call_connection_made=True): """Create SSL transport.""" raise NotImplementedError @@ -795,6 +802,42 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): return transport, protocol + async def start_tls(self, transport, protocol, sslcontext, *, + server_side=False, + server_hostname=None, + ssl_handshake_timeout=None): + """Upgrade transport to TLS. + + Return a new transport that *protocol* should start using + immediately. + """ + if ssl is None: + raise RuntimeError('Python ssl module is not available') + + if not isinstance(sslcontext, ssl.SSLContext): + raise TypeError( + f'sslcontext is expected to be an instance of ssl.SSLContext, ' + f'got {sslcontext!r}') + + if not getattr(transport, '_start_tls_compatible', False): + raise TypeError( + f'transport {self!r} is not supported by start_tls()') + + waiter = self.create_future() + ssl_protocol = sslproto.SSLProtocol( + self, protocol, sslcontext, waiter, + server_side, server_hostname, + ssl_handshake_timeout=ssl_handshake_timeout, + call_connection_made=False) + + transport.set_protocol(ssl_protocol) + self.call_soon(ssl_protocol.connection_made, transport) + if not transport.is_reading(): + self.call_soon(transport.resume_reading) + + await waiter + return ssl_protocol._app_transport + async def create_datagram_endpoint(self, protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 3a5dbadbb10..9496d5c765f 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -305,6 +305,17 @@ def set_default_executor(self, executor): """ raise NotImplementedError + async def start_tls(self, transport, protocol, sslcontext, *, + server_side=False, + server_hostname=None, + ssl_handshake_timeout=None): + """Upgrade a transport to TLS. + + Return a new transport that *protocol* should start using + immediately. + """ + raise NotImplementedError + async def create_unix_connection( self, protocol_factory, path=None, *, ssl=None, sock=None, diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 2661cddef73..ab1285b7999 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -223,6 +223,8 @@ class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport, transports.WriteTransport): """Transport for write pipes.""" + _start_tls_compatible = True + def write(self, data): if not isinstance(data, (bytes, bytearray, memoryview)): raise TypeError( diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 1e4bd83a1b1..5692e38486a 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -694,6 +694,8 @@ def get_write_buffer_size(self): class _SelectorSocketTransport(_SelectorTransport): + _start_tls_compatible = True + def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): super().__init__(loop, sock, protocol, extra, server) diff --git a/Lib/test/test_asyncio/functional.py b/Lib/test/test_asyncio/functional.py new file mode 100644 index 00000000000..5fd174b6f43 --- /dev/null +++ b/Lib/test/test_asyncio/functional.py @@ -0,0 +1,279 @@ +import asyncio +import asyncio.events +import contextlib +import os +import pprint +import select +import socket +import ssl +import tempfile +import threading + + +class FunctionalTestCaseMixin: + + def new_loop(self): + return asyncio.new_event_loop() + + def run_loop_briefly(self, *, delay=0.01): + self.loop.run_until_complete(asyncio.sleep(delay, loop=self.loop)) + + def loop_exception_handler(self, loop, context): + self.__unhandled_exceptions.append(context) + self.loop.default_exception_handler(context) + + def setUp(self): + self.loop = self.new_loop() + asyncio.set_event_loop(None) + + self.loop.set_exception_handler(self.loop_exception_handler) + self.__unhandled_exceptions = [] + + # Disable `_get_running_loop`. + self._old_get_running_loop = asyncio.events._get_running_loop + asyncio.events._get_running_loop = lambda: None + + def tearDown(self): + try: + self.loop.close() + + if self.__unhandled_exceptions: + print('Unexpected calls to loop.call_exception_handler():') + pprint.pprint(self.__unhandled_exceptions) + self.fail('unexpected calls to loop.call_exception_handler()') + + finally: + asyncio.events._get_running_loop = self._old_get_running_loop + asyncio.set_event_loop(None) + self.loop = None + + def tcp_server(self, server_prog, *, + family=socket.AF_INET, + addr=None, + timeout=5, + backlog=1, + max_clients=10): + + if addr is None: + if hasattr(socket, 'AF_UNIX') and family == socket.AF_UNIX: + with tempfile.NamedTemporaryFile() as tmp: + addr = tmp.name + else: + addr = ('127.0.0.1', 0) + + sock = socket.socket(family, socket.SOCK_STREAM) + + if timeout is None: + raise RuntimeError('timeout is required') + if timeout <= 0: + raise RuntimeError('only blocking sockets are supported') + sock.settimeout(timeout) + + try: + sock.bind(addr) + sock.listen(backlog) + except OSError as ex: + sock.close() + raise ex + + return TestThreadedServer( + self, sock, server_prog, timeout, max_clients) + + def tcp_client(self, client_prog, + family=socket.AF_INET, + timeout=10): + + sock = socket.socket(family, socket.SOCK_STREAM) + + if timeout is None: + raise RuntimeError('timeout is required') + if timeout <= 0: + raise RuntimeError('only blocking sockets are supported') + sock.settimeout(timeout) + + return TestThreadedClient( + self, sock, client_prog, timeout) + + def unix_server(self, *args, **kwargs): + if not hasattr(socket, 'AF_UNIX'): + raise NotImplementedError + return self.tcp_server(*args, family=socket.AF_UNIX, **kwargs) + + def unix_client(self, *args, **kwargs): + if not hasattr(socket, 'AF_UNIX'): + raise NotImplementedError + return self.tcp_client(*args, family=socket.AF_UNIX, **kwargs) + + @contextlib.contextmanager + def unix_sock_name(self): + with tempfile.TemporaryDirectory() as td: + fn = os.path.join(td, 'sock') + try: + yield fn + finally: + try: + os.unlink(fn) + except OSError: + pass + + def _abort_socket_test(self, ex): + try: + self.loop.stop() + finally: + self.fail(ex) + + +############################################################################## +# Socket Testing Utilities +############################################################################## + + +class TestSocketWrapper: + + def __init__(self, sock): + self.__sock = sock + + def recv_all(self, n): + buf = b'' + while len(buf) < n: + data = self.recv(n - len(buf)) + if data == b'': + raise ConnectionAbortedError + buf += data + return buf + + def start_tls(self, ssl_context, *, + server_side=False, + server_hostname=None): + + assert isinstance(ssl_context, ssl.SSLContext) + + ssl_sock = ssl_context.wrap_socket( + self.__sock, server_side=server_side, + server_hostname=server_hostname, + do_handshake_on_connect=False) + + ssl_sock.do_handshake() + + self.__sock.close() + self.__sock = ssl_sock + + def __getattr__(self, name): + return getattr(self.__sock, name) + + def __repr__(self): + return '<{} {!r}>'.format(type(self).__name__, self.__sock) + + +class SocketThread(threading.Thread): + + def stop(self): + self._active = False + self.join() + + def __enter__(self): + self.start() + return self + + def __exit__(self, *exc): + self.stop() + + +class TestThreadedClient(SocketThread): + + def __init__(self, test, sock, prog, timeout): + threading.Thread.__init__(self, None, None, 'test-client') + self.daemon = True + + self._timeout = timeout + self._sock = sock + self._active = True + self._prog = prog + self._test = test + + def run(self): + try: + self._prog(TestSocketWrapper(self._sock)) + except Exception as ex: + self._test._abort_socket_test(ex) + + +class TestThreadedServer(SocketThread): + + def __init__(self, test, sock, prog, timeout, max_clients): + threading.Thread.__init__(self, None, None, 'test-server') + self.daemon = True + + self._clients = 0 + self._finished_clients = 0 + self._max_clients = max_clients + self._timeout = timeout + self._sock = sock + self._active = True + + self._prog = prog + + self._s1, self._s2 = socket.socketpair() + self._s1.setblocking(False) + + self._test = test + + def stop(self): + try: + if self._s2 and self._s2.fileno() != -1: + try: + self._s2.send(b'stop') + except OSError: + pass + finally: + super().stop() + + def run(self): + try: + with self._sock: + self._sock.setblocking(0) + self._run() + finally: + self._s1.close() + self._s2.close() + + def _run(self): + while self._active: + if self._clients >= self._max_clients: + return + + r, w, x = select.select( + [self._sock, self._s1], [], [], self._timeout) + + if self._s1 in r: + return + + if self._sock in r: + try: + conn, addr = self._sock.accept() + except BlockingIOError: + continue + except socket.timeout: + if not self._active: + return + else: + raise + else: + self._clients += 1 + conn.settimeout(self._timeout) + try: + with conn: + self._handle_client(conn) + except Exception as ex: + self._active = False + try: + raise + finally: + self._test._abort_socket_test(ex) + + def _handle_client(self, sock): + self._prog(TestSocketWrapper(sock)) + + @property + def addr(self): + return self._sock.getsockname() diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 79e8d79e6b1..da2e036648b 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -31,21 +31,7 @@ from asyncio import proactor_events from asyncio import selector_events from test.test_asyncio import utils as test_utils -try: - from test import support -except ImportError: - from asyncio import test_support as support - - -def data_file(filename): - if hasattr(support, 'TEST_HOME_DIR'): - fullname = os.path.join(support.TEST_HOME_DIR, filename) - if os.path.isfile(fullname): - return fullname - fullname = os.path.join(os.path.dirname(__file__), filename) - if os.path.isfile(fullname): - return fullname - raise FileNotFoundError(filename) +from test import support def osx_tiger(): @@ -80,23 +66,6 @@ def __await__(self): pass -ONLYCERT = data_file('ssl_cert.pem') -ONLYKEY = data_file('ssl_key.pem') -SIGNED_CERTFILE = data_file('keycert3.pem') -SIGNING_CA = data_file('pycacert.pem') -PEERCERT = {'serialNumber': 'B09264B1F2DA21D1', - 'version': 1, - 'subject': ((('countryName', 'XY'),), - (('localityName', 'Castle Anthrax'),), - (('organizationName', 'Python Software Foundation'),), - (('commonName', 'localhost'),)), - 'issuer': ((('countryName', 'XY'),), - (('organizationName', 'Python Software Foundation CA'),), - (('commonName', 'our-ca-server'),)), - 'notAfter': 'Nov 13 19:47:07 2022 GMT', - 'notBefore': 'Jan 4 19:47:07 2013 GMT'} - - class MyBaseProto(asyncio.Protocol): connected = None done = None @@ -853,16 +822,8 @@ def test_ssl_connect_accepted_socket(self): 'SSL not supported with proactor event loops before Python 3.5' ) - server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - server_context.load_cert_chain(ONLYCERT, ONLYKEY) - if hasattr(server_context, 'check_hostname'): - server_context.check_hostname = False - server_context.verify_mode = ssl.CERT_NONE - - client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - if hasattr(server_context, 'check_hostname'): - client_context.check_hostname = False - client_context.verify_mode = ssl.CERT_NONE + server_context = test_utils.simple_server_sslcontext() + client_context = test_utils.simple_client_sslcontext() self.test_connect_accepted_socket(server_context, client_context) @@ -1048,7 +1009,7 @@ def _make_ssl_unix_server(self, factory, certfile, keyfile=None): def test_create_server_ssl(self): proto = MyProto(loop=self.loop) server, host, port = self._make_ssl_server( - lambda: proto, ONLYCERT, ONLYKEY) + lambda: proto, test_utils.ONLYCERT, test_utils.ONLYKEY) f_c = self.loop.create_connection(MyBaseProto, host, port, ssl=test_utils.dummy_ssl_context()) @@ -1081,7 +1042,7 @@ def test_create_server_ssl(self): def test_create_unix_server_ssl(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( - lambda: proto, ONLYCERT, ONLYKEY) + lambda: proto, test_utils.ONLYCERT, test_utils.ONLYKEY) f_c = self.loop.create_unix_connection( MyBaseProto, path, ssl=test_utils.dummy_ssl_context(), @@ -1111,7 +1072,7 @@ def test_create_unix_server_ssl(self): def test_create_server_ssl_verify_failed(self): proto = MyProto(loop=self.loop) server, host, port = self._make_ssl_server( - lambda: proto, SIGNED_CERTFILE) + lambda: proto, test_utils.SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext_client.options |= ssl.OP_NO_SSLv2 @@ -1141,7 +1102,7 @@ def test_create_server_ssl_verify_failed(self): def test_create_unix_server_ssl_verify_failed(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( - lambda: proto, SIGNED_CERTFILE) + lambda: proto, test_utils.SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext_client.options |= ssl.OP_NO_SSLv2 @@ -1170,13 +1131,13 @@ def test_create_unix_server_ssl_verify_failed(self): def test_create_server_ssl_match_failed(self): proto = MyProto(loop=self.loop) server, host, port = self._make_ssl_server( - lambda: proto, SIGNED_CERTFILE) + lambda: proto, test_utils.SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext_client.options |= ssl.OP_NO_SSLv2 sslcontext_client.verify_mode = ssl.CERT_REQUIRED sslcontext_client.load_verify_locations( - cafile=SIGNING_CA) + cafile=test_utils.SIGNING_CA) if hasattr(sslcontext_client, 'check_hostname'): sslcontext_client.check_hostname = True @@ -1199,12 +1160,12 @@ def test_create_server_ssl_match_failed(self): def test_create_unix_server_ssl_verified(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( - lambda: proto, SIGNED_CERTFILE) + lambda: proto, test_utils.SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext_client.options |= ssl.OP_NO_SSLv2 sslcontext_client.verify_mode = ssl.CERT_REQUIRED - sslcontext_client.load_verify_locations(cafile=SIGNING_CA) + sslcontext_client.load_verify_locations(cafile=test_utils.SIGNING_CA) if hasattr(sslcontext_client, 'check_hostname'): sslcontext_client.check_hostname = True @@ -1224,12 +1185,12 @@ def test_create_unix_server_ssl_verified(self): def test_create_server_ssl_verified(self): proto = MyProto(loop=self.loop) server, host, port = self._make_ssl_server( - lambda: proto, SIGNED_CERTFILE) + lambda: proto, test_utils.SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext_client.options |= ssl.OP_NO_SSLv2 sslcontext_client.verify_mode = ssl.CERT_REQUIRED - sslcontext_client.load_verify_locations(cafile=SIGNING_CA) + sslcontext_client.load_verify_locations(cafile=test_utils.SIGNING_CA) if hasattr(sslcontext_client, 'check_hostname'): sslcontext_client.check_hostname = True @@ -1241,7 +1202,7 @@ def test_create_server_ssl_verified(self): # extra info is available self.check_ssl_extra_info(client,peername=(host, port), - peercert=PEERCERT) + peercert=test_utils.PEERCERT) # close connection proto.transport.close() diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index a7498e85c25..886c5cf3626 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -13,6 +13,7 @@ from asyncio import sslproto from asyncio import tasks from test.test_asyncio import utils as test_utils +from test.test_asyncio import functional as func_tests @unittest.skipIf(ssl is None, 'No ssl module') @@ -158,5 +159,156 @@ def test_set_new_app_protocol(self): self.assertIs(ssl_proto._app_protocol, new_app_proto) +############################################################################## +# Start TLS Tests +############################################################################## + + +class BaseStartTLS(func_tests.FunctionalTestCaseMixin): + + def new_loop(self): + raise NotImplementedError + + def test_start_tls_client_1(self): + HELLO_MSG = b'1' * 1024 * 1024 * 5 + + server_context = test_utils.simple_server_sslcontext() + client_context = test_utils.simple_client_sslcontext() + + def serve(sock): + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + + sock.start_tls(server_context, server_side=True) + + sock.sendall(b'O') + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + sock.close() + + class ClientProto(asyncio.Protocol): + def __init__(self, on_data, on_eof): + self.on_data = on_data + self.on_eof = on_eof + self.con_made_cnt = 0 + + def connection_made(proto, tr): + proto.con_made_cnt += 1 + # Ensure connection_made gets called only once. + self.assertEqual(proto.con_made_cnt, 1) + + def data_received(self, data): + self.on_data.set_result(data) + + def eof_received(self): + self.on_eof.set_result(True) + + async def client(addr): + on_data = self.loop.create_future() + on_eof = self.loop.create_future() + + tr, proto = await self.loop.create_connection( + lambda: ClientProto(on_data, on_eof), *addr) + + tr.write(HELLO_MSG) + new_tr = await self.loop.start_tls(tr, proto, client_context) + + self.assertEqual(await on_data, b'O') + new_tr.write(HELLO_MSG) + await on_eof + + new_tr.close() + + with self.tcp_server(serve) as srv: + self.loop.run_until_complete( + asyncio.wait_for(client(srv.addr), loop=self.loop, timeout=10)) + + def test_start_tls_server_1(self): + HELLO_MSG = b'1' * 1024 * 1024 * 5 + + server_context = test_utils.simple_server_sslcontext() + client_context = test_utils.simple_client_sslcontext() + + def client(sock, addr): + sock.connect(addr) + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + + sock.start_tls(client_context) + sock.sendall(HELLO_MSG) + sock.close() + + class ServerProto(asyncio.Protocol): + def __init__(self, on_con, on_eof): + self.on_con = on_con + self.on_eof = on_eof + self.data = b'' + + def connection_made(self, tr): + self.on_con.set_result(tr) + + def data_received(self, data): + self.data += data + + def eof_received(self): + self.on_eof.set_result(1) + + async def main(): + tr = await on_con + tr.write(HELLO_MSG) + + self.assertEqual(proto.data, b'') + + new_tr = await self.loop.start_tls( + tr, proto, server_context, + server_side=True) + + await on_eof + self.assertEqual(proto.data, HELLO_MSG) + new_tr.close() + + server.close() + await server.wait_closed() + + on_con = self.loop.create_future() + on_eof = self.loop.create_future() + proto = ServerProto(on_con, on_eof) + + server = self.loop.run_until_complete( + self.loop.create_server( + lambda: proto, '127.0.0.1', 0)) + addr = server.sockets[0].getsockname() + + with self.tcp_client(lambda sock: client(sock, addr)): + self.loop.run_until_complete( + asyncio.wait_for(main(), loop=self.loop, timeout=10)) + + def test_start_tls_wrong_args(self): + async def main(): + with self.assertRaisesRegex(TypeError, 'SSLContext, got'): + await self.loop.start_tls(None, None, None) + + sslctx = test_utils.simple_server_sslcontext() + with self.assertRaisesRegex(TypeError, 'is not supported'): + await self.loop.start_tls(None, None, sslctx) + + self.loop.run_until_complete(main()) + + + at unittest.skipIf(ssl is None, 'No ssl module') +class SelectorStartTLS(BaseStartTLS, unittest.TestCase): + + def new_loop(self): + return asyncio.SelectorEventLoop() + + + at unittest.skipIf(ssl is None, 'No ssl module') + at unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') +class ProactorStartTLS(BaseStartTLS, unittest.TestCase): + + def new_loop(self): + return asyncio.ProactorEventLoop() + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index eaafe3af8b8..a78e01988d8 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -35,6 +35,49 @@ from test import support +def data_file(filename): + if hasattr(support, 'TEST_HOME_DIR'): + fullname = os.path.join(support.TEST_HOME_DIR, filename) + if os.path.isfile(fullname): + return fullname + fullname = os.path.join(os.path.dirname(__file__), filename) + if os.path.isfile(fullname): + return fullname + raise FileNotFoundError(filename) + + +ONLYCERT = data_file('ssl_cert.pem') +ONLYKEY = data_file('ssl_key.pem') +SIGNED_CERTFILE = data_file('keycert3.pem') +SIGNING_CA = data_file('pycacert.pem') +PEERCERT = {'serialNumber': 'B09264B1F2DA21D1', + 'version': 1, + 'subject': ((('countryName', 'XY'),), + (('localityName', 'Castle Anthrax'),), + (('organizationName', 'Python Software Foundation'),), + (('commonName', 'localhost'),)), + 'issuer': ((('countryName', 'XY'),), + (('organizationName', 'Python Software Foundation CA'),), + (('commonName', 'our-ca-server'),)), + 'notAfter': 'Nov 13 19:47:07 2022 GMT', + 'notBefore': 'Jan 4 19:47:07 2013 GMT'} + + +def simple_server_sslcontext(): + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + server_context.load_cert_chain(ONLYCERT, ONLYKEY) + server_context.check_hostname = False + server_context.verify_mode = ssl.CERT_NONE + return server_context + + +def simple_client_sslcontext(): + client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + client_context.check_hostname = False + client_context.verify_mode = ssl.CERT_NONE + return client_context + + def dummy_ssl_context(): if ssl is None: return None diff --git a/Misc/NEWS.d/next/Library/2017-12-29-00-44-42.bpo-23749.QL1Cxd.rst b/Misc/NEWS.d/next/Library/2017-12-29-00-44-42.bpo-23749.QL1Cxd.rst new file mode 100644 index 00000000000..d6de1fef901 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-29-00-44-42.bpo-23749.QL1Cxd.rst @@ -0,0 +1 @@ +asyncio: Implement loop.start_tls() From webhook-mailer at python.org Sat Dec 30 02:47:48 2017 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 30 Dec 2017 07:47:48 -0000 Subject: [Python-checkins] bpo-32439: Clean up the code for compiling comparison expressions. (#5029) Message-ID: https://github.com/python/cpython/commit/02b9ef27752ff4873c592ac3afe7e3410f715984 commit: 02b9ef27752ff4873c592ac3afe7e3410f715984 branch: master author: Serhiy Storchaka committer: GitHub date: 2017-12-30T09:47:42+02:00 summary: bpo-32439: Clean up the code for compiling comparison expressions. (#5029) files: M Python/compile.c diff --git a/Python/compile.c b/Python/compile.c index e5745d16e30..cd039168eba 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3420,35 +3420,32 @@ static int compiler_compare(struct compiler *c, expr_ty e) { Py_ssize_t i, n; - basicblock *cleanup = NULL; - /* XXX the logic can be cleaned up for 1 or multiple comparisons */ VISIT(c, expr, e->v.Compare.left); - n = asdl_seq_LEN(e->v.Compare.ops); - assert(n > 0); - if (n > 1) { - cleanup = compiler_new_block(c); + assert(asdl_seq_LEN(e->v.Compare.ops) > 0); + n = asdl_seq_LEN(e->v.Compare.ops) - 1; + if (n == 0) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); + ADDOP_I(c, COMPARE_OP, + cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, 0)))); + } + else { + basicblock *cleanup = compiler_new_block(c); if (cleanup == NULL) return 0; - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); - } - for (i = 1; i < n; i++) { - ADDOP(c, DUP_TOP); - ADDOP(c, ROT_THREE); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET( - e->v.Compare.ops, i - 1)))); - ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); - NEXT_BLOCK(c); - if (i < (n - 1)) + for (i = 0; i < n; i++) { VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n - 1)); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n - 1)))); - if (n > 1) { + ADDOP(c, DUP_TOP); + ADDOP(c, ROT_THREE); + ADDOP_I(c, COMPARE_OP, + cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, i)))); + ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); + NEXT_BLOCK(c); + } + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); + ADDOP_I(c, COMPARE_OP, + cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n)))); basicblock *end = compiler_new_block(c); if (end == NULL) return 0; From solipsis at pitrou.net Sat Dec 30 04:13:27 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 30 Dec 2017 09:13:27 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=1 Message-ID: <20171230091326.1.DCB386412D958141@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [-7, 1, 0] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, 0, -2] memory blocks, sum=-2 test_multiprocessing_forkserver leaked [2, 0, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog4uE42t', '--timeout', '7200'] From webhook-mailer at python.org Sat Dec 30 08:40:31 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 30 Dec 2017 13:40:31 -0000 Subject: [Python-checkins] Fix typo (#5049) Message-ID: https://github.com/python/cpython/commit/fc35932afdad91f87b49a4854d4333267494c6c1 commit: fc35932afdad91f87b49a4854d4333267494c6c1 branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-30T15:40:27+02:00 summary: Fix typo (#5049) files: M Modules/_asynciomodule.c diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 5ec4ad182ab..22ce32c593c 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2265,7 +2265,7 @@ _asyncio_Task_set_exception(TaskObj *self, PyObject *exception) /*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/ { PyErr_SetString(PyExc_RuntimeError, - "Task doed not support set_exception operation"); + "Task does not support set_exception operation"); return NULL; } From webhook-mailer at python.org Sat Dec 30 10:09:39 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 30 Dec 2017 15:09:39 -0000 Subject: [Python-checkins] bpo-32418: Add get_loop() method on Server, AbstractServer classes (#4997) Message-ID: https://github.com/python/cpython/commit/1634fc289a13b0e1fdad4694d5cae7dab55f7186 commit: 1634fc289a13b0e1fdad4694d5cae7dab55f7186 branch: master author: Srinivas Reddy Thatiparthy (?????????? ?????? ?????????) committer: Andrew Svetlov date: 2017-12-30T17:09:32+02:00 summary: bpo-32418: Add get_loop() method on Server, AbstractServer classes (#4997) * Add abstract get_loop() method to Server, AbstractServer classes. * Add test cases for get_loop() method in Server, AbstractServer classes * Add documentation for get_loop() method files: A Misc/NEWS.d/next/Documentation/2017-12-24-17-29-37.bpo-32418.eZe-ID.rst M Doc/library/asyncio-eventloop.rst M Lib/asyncio/base_events.py M Lib/asyncio/events.py M Lib/test/test_asyncio/test_events.py diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 33b86d6f033..4fbbcd86cf4 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -913,6 +913,12 @@ Server The server is closed asynchronously, use the :meth:`wait_closed` coroutine to wait until the server is closed. + .. method:: get_loop() + + Gives the event loop associated with the server object. + + .. versionadded:: 3.7 + .. coroutinemethod:: wait_closed() Wait until the :meth:`close` method completes. diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 00831b39853..ab002319c18 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -185,6 +185,9 @@ def close(self): if self._active_count == 0: self._wakeup() + def get_loop(self): + return self._loop + def _wakeup(self): waiters = self._waiters self._waiters = None diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 9496d5c765f..731a0c5e802 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -155,6 +155,10 @@ def close(self): """Coroutine to wait until service is closed.""" return NotImplemented + def get_loop(self): + """ Get the event loop the Server object is attached to.""" + return NotImplemented + class AbstractEventLoop: """Abstract event loop.""" diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index da2e036648b..e8320564c74 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2826,6 +2826,19 @@ class TestCGetEventLoop(GetEventLoopTestsMixin, unittest.TestCase): get_running_loop_impl = events._c_get_running_loop get_event_loop_impl = events._c_get_event_loop +class TestServer(unittest.TestCase): + + def test_get_loop(self): + loop = asyncio.new_event_loop() + proto = MyProto(loop) + server = loop.run_until_complete(loop.create_server(lambda: proto, '0.0.0.0', 0)) + self.assertEqual(server.get_loop(), loop) + loop.close() + +class TestAbstractServer(unittest.TestCase): + + def test_get_loop(self): + self.assertEqual(events.AbstractServer().get_loop(), NotImplemented) if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Documentation/2017-12-24-17-29-37.bpo-32418.eZe-ID.rst b/Misc/NEWS.d/next/Documentation/2017-12-24-17-29-37.bpo-32418.eZe-ID.rst new file mode 100644 index 00000000000..9441b74ef84 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2017-12-24-17-29-37.bpo-32418.eZe-ID.rst @@ -0,0 +1 @@ +Add get_loop() method to Server and AbstractServer classes. From webhook-mailer at python.org Sat Dec 30 11:52:59 2017 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 30 Dec 2017 16:52:59 -0000 Subject: [Python-checkins] bpo-32418: Postfix, raise NotImplementdError and close resources in tests (#5052) Message-ID: https://github.com/python/cpython/commit/ffcb4c0165827d0a48ea973cc88bc134c74879fb commit: ffcb4c0165827d0a48ea973cc88bc134c74879fb branch: master author: Andrew Svetlov committer: GitHub date: 2017-12-30T18:52:56+02:00 summary: bpo-32418: Postfix, raise NotImplementdError and close resources in tests (#5052) files: M Lib/asyncio/events.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 731a0c5e802..af4545b2cbe 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -149,15 +149,15 @@ class AbstractServer: def close(self): """Stop serving. This leaves existing connections open.""" - return NotImplemented + raise NotImplementedError async def wait_closed(self): """Coroutine to wait until service is closed.""" - return NotImplemented + raise NotImplementedError def get_loop(self): """ Get the event loop the Server object is attached to.""" - return NotImplemented + raise NotImplementedError class AbstractEventLoop: diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index e8320564c74..f63fd3c723a 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2826,19 +2826,36 @@ class TestCGetEventLoop(GetEventLoopTestsMixin, unittest.TestCase): get_running_loop_impl = events._c_get_running_loop get_event_loop_impl = events._c_get_event_loop + class TestServer(unittest.TestCase): def test_get_loop(self): loop = asyncio.new_event_loop() + self.addCleanup(loop.close) proto = MyProto(loop) server = loop.run_until_complete(loop.create_server(lambda: proto, '0.0.0.0', 0)) self.assertEqual(server.get_loop(), loop) - loop.close() + server.close() + loop.run_until_complete(server.wait_closed()) + class TestAbstractServer(unittest.TestCase): + def test_close(self): + with self.assertRaises(NotImplementedError): + events.AbstractServer().close() + + def test_wait_closed(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + with self.assertRaises(NotImplementedError): + loop.run_until_complete(events.AbstractServer().wait_closed()) + def test_get_loop(self): - self.assertEqual(events.AbstractServer().get_loop(), NotImplemented) + with self.assertRaises(NotImplementedError): + events.AbstractServer().get_loop() + if __name__ == '__main__': unittest.main() From webhook-mailer at python.org Sat Dec 30 15:18:09 2017 From: webhook-mailer at python.org (Barry Warsaw) Date: Sat, 30 Dec 2017 20:18:09 -0000 Subject: [Python-checkins] bpo-32248 - Implement importlib.resources (#4911) Message-ID: https://github.com/python/cpython/commit/deae6b451fefd5fd3143dd65051e1d341e5a5f84 commit: deae6b451fefd5fd3143dd65051e1d341e5a5f84 branch: master author: Barry Warsaw committer: GitHub date: 2017-12-30T15:18:06-05:00 summary: bpo-32248 - Implement importlib.resources (#4911) Port importlib_resources to importlib.resources files: A Lib/importlib/resources.py A Lib/test/test_importlib/data01/__init__.py A Lib/test/test_importlib/data01/binary.file A Lib/test/test_importlib/data01/subdirectory/__init__.py A Lib/test/test_importlib/data01/subdirectory/binary.file A Lib/test/test_importlib/data01/utf-16.file A Lib/test/test_importlib/data01/utf-8.file A Lib/test/test_importlib/data02/__init__.py A Lib/test/test_importlib/data02/one/__init__.py A Lib/test/test_importlib/data02/one/resource1.txt A Lib/test/test_importlib/data02/two/__init__.py A Lib/test/test_importlib/data02/two/resource2.txt A Lib/test/test_importlib/data03/__init__.py A Lib/test/test_importlib/data03/namespace/portion1/__init__.py A Lib/test/test_importlib/data03/namespace/portion2/__init__.py A Lib/test/test_importlib/data03/namespace/resource1.txt A Lib/test/test_importlib/test_open.py A Lib/test/test_importlib/test_path.py A Lib/test/test_importlib/test_read.py A Lib/test/test_importlib/test_resource.py A Lib/test/test_importlib/zipdata01/__init__.py A Lib/test/test_importlib/zipdata01/ziptestdata.zip A Lib/test/test_importlib/zipdata02/__init__.py A Lib/test/test_importlib/zipdata02/ziptestdata.zip M Doc/library/importlib.rst M Doc/whatsnew/3.7.rst M Lib/test/test_importlib/util.py M Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index eeccc9d40e6..e99c6067a3d 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -484,7 +484,7 @@ ABC hierarchy:: versus on the file system. For any of methods of this class, a *resource* argument is - expected to be a :term:`file-like object` which represents + expected to be a :term:`path-like object` which represents conceptually just a file name. This means that no subdirectory paths should be included in the *resource* argument. This is because the location of the package that the loader is for acts @@ -775,6 +775,131 @@ ABC hierarchy:: itself does not end in ``__init__``. +:mod:`importlib.resources` -- Resources +--------------------------------------- + +.. module:: importlib.resources + :synopsis: Package resource reading, opening, and access + +**Source code:** :source:`Lib/importlib/resources.py` + +-------------- + +.. versionadded:: 3.7 + +This module leverages Python's import system to provide access to *resources* +within *packages*. If you can import a package, you can access resources +within that package. Resources can be opened or read, in either binary or +text mode. + +Resources are roughly akin to files inside directories, though it's important +to keep in mind that this is just a metaphor. Resources and packages **do +not** have to exist as physical files and directories on the file system. + +Loaders can support resources by implementing the :class:`ResourceReader` +abstract base class. + +The following types are defined. + +.. data:: Package + + The ``Package`` type is defined as ``Union[str, ModuleType]``. This means + that where the function describes accepting a ``Package``, you can pass in + either a string or a module. Module objects must have a resolvable + ``__spec__.submodule_search_locations`` that is not ``None``. + +.. data:: Resource + + This type describes the resource names passed into the various functions + in this package. This is defined as ``Union[str, os.PathLike]``. + + +The following functions are available. + +.. function:: open_binary(package, resource) + + Open for binary reading the *resource* within *package*. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). This function returns a + ``typing.BinaryIO`` instance, a binary I/O stream open for reading. + + +.. function:: open_text(package, resource, encoding='utf-8', errors='strict') + + Open for text reading the *resource* within *package*. By default, the + resource is opened for reading as UTF-8. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). *encoding* and *errors* + have the same meaning as with built-in :func:`open`. + + This function returns a ``typing.TextIO`` instance, a text I/O stream open + for reading. + + +.. function:: read_binary(package, resource) + + Read and return the contents of the *resource* within *package* as + ``bytes``. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). This function returns the + contents of the resource as :class:`bytes`. + + +.. function:: read_text(package, resource, encoding='utf-8', errors='strict') + + Read and return the contents of *resource* within *package* as a ``str``. + By default, the contents are read as strict UTF-8. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). *encoding* and *errors* + have the same meaning as with built-in :func:`open`. This function + returns the contents of the resource as :class:`str`. + + +.. function:: path(package, resource) + + Return the path to the *resource* as an actual file system path. This + function returns a context manager for use in a :keyword:`with` statement. + The context manager provides a :class:`pathlib.Path` object. + + Exiting the context manager cleans up any temporary file created when the + resource needs to be extracted from e.g. a zip file. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). + + +.. function:: is_resource(package, name) + + Return ``True`` if there is a resource named *name* in the package, + otherwise ``False``. Remember that directories are *not* resources! + *package* is either a name or a module object which conforms to the + ``Package`` requirements. + + +.. function:: contents(package) + + Return an iterator over the named items within the package. The iterator + returns :class:`str` resources (e.g. files) and non-resources + (e.g. directories). The iterator does not recurse into subdirectories. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. + + :mod:`importlib.machinery` -- Importers and path hooks ------------------------------------------------------ diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index e5523ff7fd2..1924881219a 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -282,7 +282,14 @@ Other Language Changes New Modules =========== -* None yet. +importlib.resources +------------------- + +This module provides several new APIs and one new ABC for access to, opening, +and reading *resources* inside packages. Resources are roughly akin to files +inside of packages, but they needn't be actual files on the physical file +system. Module loaders can implement the +:class:`importlib.abc.ResourceReader` ABC to support this new module's API. Improved Modules diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py new file mode 100644 index 00000000000..8511f24d8e7 --- /dev/null +++ b/Lib/importlib/resources.py @@ -0,0 +1,303 @@ +import os +import tempfile + +from . import abc as resources_abc +from builtins import open as builtins_open +from contextlib import contextmanager, suppress +from importlib import import_module +from importlib.abc import ResourceLoader +from io import BytesIO, TextIOWrapper +from pathlib import Path +from types import ModuleType +from typing import Iterator, Optional, Set, Union # noqa: F401 +from typing import cast +from typing.io import BinaryIO, TextIO +from zipfile import ZipFile + + +Package = Union[str, ModuleType] +Resource = Union[str, os.PathLike] + + +def _get_package(package) -> ModuleType: + """Take a package name or module object and return the module. + + If a name, the module is imported. If the passed or imported module + object is not a package, raise an exception. + """ + if hasattr(package, '__spec__'): + if package.__spec__.submodule_search_locations is None: + raise TypeError('{!r} is not a package'.format( + package.__spec__.name)) + else: + return package + else: + module = import_module(package) + if module.__spec__.submodule_search_locations is None: + raise TypeError('{!r} is not a package'.format(package)) + else: + return module + + +def _normalize_path(path) -> str: + """Normalize a path by ensuring it is a string. + + If the resulting string contains path separators, an exception is raised. + """ + str_path = str(path) + parent, file_name = os.path.split(str_path) + if parent: + raise ValueError('{!r} must be only a file name'.format(path)) + else: + return file_name + + +def _get_resource_reader( + package: ModuleType) -> Optional[resources_abc.ResourceReader]: + # Return the package's loader if it's a ResourceReader. We can't use + # a issubclass() check here because apparently abc.'s __subclasscheck__() + # hook wants to create a weak reference to the object, but + # zipimport.zipimporter does not support weak references, resulting in a + # TypeError. That seems terrible. + if hasattr(package.__spec__.loader, 'open_resource'): + return cast(resources_abc.ResourceReader, package.__spec__.loader) + return None + + +def open_binary(package: Package, resource: Resource) -> BinaryIO: + """Return a file-like object opened for binary reading of the resource.""" + resource = _normalize_path(resource) + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + return reader.open_resource(resource) + absolute_package_path = os.path.abspath(package.__spec__.origin) + package_path = os.path.dirname(absolute_package_path) + full_path = os.path.join(package_path, resource) + try: + return builtins_open(full_path, mode='rb') + except OSError: + # Just assume the loader is a resource loader; all the relevant + # importlib.machinery loaders are and an AttributeError for + # get_data() will make it clear what is needed from the loader. + loader = cast(ResourceLoader, package.__spec__.loader) + data = None + if hasattr(package.__spec__.loader, 'get_data'): + with suppress(OSError): + data = loader.get_data(full_path) + if data is None: + package_name = package.__spec__.name + message = '{!r} resource not found in {!r}'.format( + resource, package_name) + raise FileNotFoundError(message) + else: + return BytesIO(data) + + +def open_text(package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict') -> TextIO: + """Return a file-like object opened for text reading of the resource.""" + resource = _normalize_path(resource) + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + return TextIOWrapper(reader.open_resource(resource), encoding, errors) + absolute_package_path = os.path.abspath(package.__spec__.origin) + package_path = os.path.dirname(absolute_package_path) + full_path = os.path.join(package_path, resource) + try: + return builtins_open( + full_path, mode='r', encoding=encoding, errors=errors) + except OSError: + # Just assume the loader is a resource loader; all the relevant + # importlib.machinery loaders are and an AttributeError for + # get_data() will make it clear what is needed from the loader. + loader = cast(ResourceLoader, package.__spec__.loader) + data = None + if hasattr(package.__spec__.loader, 'get_data'): + with suppress(OSError): + data = loader.get_data(full_path) + if data is None: + package_name = package.__spec__.name + message = '{!r} resource not found in {!r}'.format( + resource, package_name) + raise FileNotFoundError(message) + else: + return TextIOWrapper(BytesIO(data), encoding, errors) + + +def read_binary(package: Package, resource: Resource) -> bytes: + """Return the binary contents of the resource.""" + resource = _normalize_path(resource) + package = _get_package(package) + with open_binary(package, resource) as fp: + return fp.read() + + +def read_text(package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict') -> str: + """Return the decoded string of the resource. + + The decoding-related arguments have the same semantics as those of + bytes.decode(). + """ + resource = _normalize_path(resource) + package = _get_package(package) + with open_text(package, resource, encoding, errors) as fp: + return fp.read() + + + at contextmanager +def path(package: Package, resource: Resource) -> Iterator[Path]: + """A context manager providing a file path object to the resource. + + If the resource does not already exist on its own on the file system, + a temporary file will be created. If the file was created, the file + will be deleted upon exiting the context manager (no exception is + raised if the file was deleted prior to the context manager + exiting). + """ + resource = _normalize_path(resource) + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + try: + yield Path(reader.resource_path(resource)) + return + except FileNotFoundError: + pass + # Fall-through for both the lack of resource_path() *and* if + # resource_path() raises FileNotFoundError. + package_directory = Path(package.__spec__.origin).parent + file_path = package_directory / resource + if file_path.exists(): + yield file_path + else: + with open_binary(package, resource) as fp: + data = fp.read() + # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try' + # blocks due to the need to close the temporary file to work on + # Windows properly. + fd, raw_path = tempfile.mkstemp() + try: + os.write(fd, data) + os.close(fd) + yield Path(raw_path) + finally: + try: + os.remove(raw_path) + except FileNotFoundError: + pass + + +def is_resource(package: Package, name: str) -> bool: + """True if 'name' is a resource inside 'package'. + + Directories are *not* resources. + """ + package = _get_package(package) + _normalize_path(name) + reader = _get_resource_reader(package) + if reader is not None: + return reader.is_resource(name) + try: + package_contents = set(contents(package)) + except (NotADirectoryError, FileNotFoundError): + return False + if name not in package_contents: + return False + # Just because the given file_name lives as an entry in the package's + # contents doesn't necessarily mean it's a resource. Directories are not + # resources, so let's try to find out if it's a directory or not. + path = Path(package.__spec__.origin).parent / name + if path.is_file(): + return True + if path.is_dir(): + return False + # If it's not a file and it's not a directory, what is it? Well, this + # means the file doesn't exist on the file system, so it probably lives + # inside a zip file. We have to crack open the zip, look at its table of + # contents, and make sure that this entry doesn't have sub-entries. + archive_path = package.__spec__.loader.archive # type: ignore + package_directory = Path(package.__spec__.origin).parent + with ZipFile(archive_path) as zf: + toc = zf.namelist() + relpath = package_directory.relative_to(archive_path) + candidate_path = relpath / name + for entry in toc: + try: + relative_to_candidate = Path(entry).relative_to(candidate_path) + except ValueError: + # The two paths aren't relative to each other so we can ignore it. + continue + # Since directories aren't explicitly listed in the zip file, we must + # infer their 'directory-ness' by looking at the number of path + # components in the path relative to the package resource we're + # looking up. If there are zero additional parts, it's a file, i.e. a + # resource. If there are more than zero it's a directory, i.e. not a + # resource. It has to be one of these two cases. + return len(relative_to_candidate.parts) == 0 + # I think it's impossible to get here. It would mean that we are looking + # for a resource in a zip file, there's an entry matching it in the return + # value of contents(), but we never actually found it in the zip's table of + # contents. + raise AssertionError('Impossible situation') + + +def contents(package: Package) -> Iterator[str]: + """Return the list of entries in 'package'. + + Note that not all entries are resources. Specifically, directories are + not considered resources. Use `is_resource()` on each entry returned here + to check if it is a resource or not. + """ + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + yield from reader.contents() + return + # Is the package a namespace package? By definition, namespace packages + # cannot have resources. + if (package.__spec__.origin == 'namespace' and + not package.__spec__.has_location): + return [] + package_directory = Path(package.__spec__.origin).parent + try: + yield from os.listdir(str(package_directory)) + except (NotADirectoryError, FileNotFoundError): + # The package is probably in a zip file. + archive_path = getattr(package.__spec__.loader, 'archive', None) + if archive_path is None: + raise + relpath = package_directory.relative_to(archive_path) + with ZipFile(archive_path) as zf: + toc = zf.namelist() + subdirs_seen = set() # type: Set + for filename in toc: + path = Path(filename) + # Strip off any path component parts that are in common with the + # package directory, relative to the zip archive's file system + # path. This gives us all the parts that live under the named + # package inside the zip file. If the length of these subparts is + # exactly 1, then it is situated inside the package. The resulting + # length will be 0 if it's above the package, and it will be + # greater than 1 if it lives in a subdirectory of the package + # directory. + # + # However, since directories themselves don't appear in the zip + # archive as a separate entry, we need to return the first path + # component for any case that has > 1 subparts -- but only once! + if path.parts[:len(relpath.parts)] != relpath.parts: + continue + subparts = path.parts[len(relpath.parts):] + if len(subparts) == 1: + yield subparts[0] + elif len(subparts) > 1: + subdir = subparts[0] + if subdir not in subdirs_seen: + subdirs_seen.add(subdir) + yield subdir diff --git a/Lib/test/test_importlib/data01/__init__.py b/Lib/test/test_importlib/data01/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data01/binary.file b/Lib/test/test_importlib/data01/binary.file new file mode 100644 index 00000000000..eaf36c1dacc Binary files /dev/null and b/Lib/test/test_importlib/data01/binary.file differ diff --git a/Lib/test/test_importlib/data01/subdirectory/__init__.py b/Lib/test/test_importlib/data01/subdirectory/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data01/subdirectory/binary.file b/Lib/test/test_importlib/data01/subdirectory/binary.file new file mode 100644 index 00000000000..eaf36c1dacc Binary files /dev/null and b/Lib/test/test_importlib/data01/subdirectory/binary.file differ diff --git a/Lib/test/test_importlib/data01/utf-16.file b/Lib/test/test_importlib/data01/utf-16.file new file mode 100644 index 00000000000..2cb772295ef Binary files /dev/null and b/Lib/test/test_importlib/data01/utf-16.file differ diff --git a/Lib/test/test_importlib/data01/utf-8.file b/Lib/test/test_importlib/data01/utf-8.file new file mode 100644 index 00000000000..1c0132ad90a --- /dev/null +++ b/Lib/test/test_importlib/data01/utf-8.file @@ -0,0 +1 @@ +Hello, UTF-8 world! diff --git a/Lib/test/test_importlib/data02/__init__.py b/Lib/test/test_importlib/data02/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data02/one/__init__.py b/Lib/test/test_importlib/data02/one/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data02/one/resource1.txt b/Lib/test/test_importlib/data02/one/resource1.txt new file mode 100644 index 00000000000..61a813e4017 --- /dev/null +++ b/Lib/test/test_importlib/data02/one/resource1.txt @@ -0,0 +1 @@ +one resource diff --git a/Lib/test/test_importlib/data02/two/__init__.py b/Lib/test/test_importlib/data02/two/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data02/two/resource2.txt b/Lib/test/test_importlib/data02/two/resource2.txt new file mode 100644 index 00000000000..a80ce46ea36 --- /dev/null +++ b/Lib/test/test_importlib/data02/two/resource2.txt @@ -0,0 +1 @@ +two resource diff --git a/Lib/test/test_importlib/data03/__init__.py b/Lib/test/test_importlib/data03/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data03/namespace/portion1/__init__.py b/Lib/test/test_importlib/data03/namespace/portion1/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data03/namespace/portion2/__init__.py b/Lib/test/test_importlib/data03/namespace/portion2/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/data03/namespace/resource1.txt b/Lib/test/test_importlib/data03/namespace/resource1.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/test_open.py b/Lib/test/test_importlib/test_open.py new file mode 100644 index 00000000000..ad236c61716 --- /dev/null +++ b/Lib/test/test_importlib/test_open.py @@ -0,0 +1,72 @@ +import unittest + +from importlib import resources +from . import data01 +from . import util + + +class CommonBinaryTests(util.CommonResourceTests, unittest.TestCase): + def execute(self, package, path): + with resources.open_binary(package, path): + pass + + +class CommonTextTests(util.CommonResourceTests, unittest.TestCase): + def execute(self, package, path): + with resources.open_text(package, path): + pass + + +class OpenTests: + def test_open_binary(self): + with resources.open_binary(self.data, 'utf-8.file') as fp: + result = fp.read() + self.assertEqual(result, b'Hello, UTF-8 world!\n') + + def test_open_text_default_encoding(self): + with resources.open_text(self.data, 'utf-8.file') as fp: + result = fp.read() + self.assertEqual(result, 'Hello, UTF-8 world!\n') + + def test_open_text_given_encoding(self): + with resources.open_text( + self.data, 'utf-16.file', 'utf-16', 'strict') as fp: + result = fp.read() + self.assertEqual(result, 'Hello, UTF-16 world!\n') + + def test_open_text_with_errors(self): + # Raises UnicodeError without the 'errors' argument. + with resources.open_text( + self.data, 'utf-16.file', 'utf-8', 'strict') as fp: + self.assertRaises(UnicodeError, fp.read) + with resources.open_text( + self.data, 'utf-16.file', 'utf-8', 'ignore') as fp: + result = fp.read() + self.assertEqual( + result, + 'H\x00e\x00l\x00l\x00o\x00,\x00 ' + '\x00U\x00T\x00F\x00-\x001\x006\x00 ' + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00') + + def test_open_binary_FileNotFoundError(self): + self.assertRaises( + FileNotFoundError, + resources.open_binary, self.data, 'does-not-exist') + + def test_open_text_FileNotFoundError(self): + self.assertRaises( + FileNotFoundError, + resources.open_text, self.data, 'does-not-exist') + + +class OpenDiskTests(OpenTests, unittest.TestCase): + def setUp(self): + self.data = data01 + + +class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_importlib/test_path.py b/Lib/test/test_importlib/test_path.py new file mode 100644 index 00000000000..2d3dcda7ed2 --- /dev/null +++ b/Lib/test/test_importlib/test_path.py @@ -0,0 +1,39 @@ +import unittest + +from importlib import resources +from . import data01 +from . import util + + +class CommonTests(util.CommonResourceTests, unittest.TestCase): + def execute(self, package, path): + with resources.path(package, path): + pass + + +class PathTests: + def test_reading(self): + # Path should be readable. + # Test also implicitly verifies the returned object is a pathlib.Path + # instance. + with resources.path(self.data, 'utf-8.file') as path: + # pathlib.Path.read_text() was introduced in Python 3.5. + with path.open('r', encoding='utf-8') as file: + text = file.read() + self.assertEqual('Hello, UTF-8 world!\n', text) + + +class PathDiskTests(PathTests, unittest.TestCase): + data = data01 + + +class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase): + def test_remove_in_context_manager(self): + # It is not an error if the file that was temporarily stashed on the + # file system is removed inside the `with` stanza. + with resources.path(self.data, 'utf-8.file') as path: + path.unlink() + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_importlib/test_read.py b/Lib/test/test_importlib/test_read.py new file mode 100644 index 00000000000..231f5017b68 --- /dev/null +++ b/Lib/test/test_importlib/test_read.py @@ -0,0 +1,53 @@ +import unittest + +from importlib import resources +from . import data01 +from . import util + + +class CommonBinaryTests(util.CommonResourceTests, unittest.TestCase): + def execute(self, package, path): + resources.read_binary(package, path) + + +class CommonTextTests(util.CommonResourceTests, unittest.TestCase): + def execute(self, package, path): + resources.read_text(package, path) + + +class ReadTests: + def test_read_binary(self): + result = resources.read_binary(self.data, 'binary.file') + self.assertEqual(result, b'\0\1\2\3') + + def test_read_text_default_encoding(self): + result = resources.read_text(self.data, 'utf-8.file') + self.assertEqual(result, 'Hello, UTF-8 world!\n') + + def test_read_text_given_encoding(self): + result = resources.read_text( + self.data, 'utf-16.file', encoding='utf-16') + self.assertEqual(result, 'Hello, UTF-16 world!\n') + + def test_read_text_with_errors(self): + # Raises UnicodeError without the 'errors' argument. + self.assertRaises( + UnicodeError, resources.read_text, self.data, 'utf-16.file') + result = resources.read_text(self.data, 'utf-16.file', errors='ignore') + self.assertEqual( + result, + 'H\x00e\x00l\x00l\x00o\x00,\x00 ' + '\x00U\x00T\x00F\x00-\x001\x006\x00 ' + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00') + + +class ReadDiskTests(ReadTests, unittest.TestCase): + data = data01 + + +class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_importlib/test_resource.py b/Lib/test/test_importlib/test_resource.py new file mode 100644 index 00000000000..c35f7897485 --- /dev/null +++ b/Lib/test/test_importlib/test_resource.py @@ -0,0 +1,143 @@ +import sys +import unittest + +from importlib import resources +from . import data01 +from . import zipdata02 +from . import util + + +class ResourceTests: + # Subclasses are expected to set the `data` attribute. + + def test_is_resource_good_path(self): + self.assertTrue(resources.is_resource(self.data, 'binary.file')) + + def test_is_resource_missing(self): + self.assertFalse(resources.is_resource(self.data, 'not-a-file')) + + def test_is_resource_subresource_directory(self): + # Directories are not resources. + self.assertFalse(resources.is_resource(self.data, 'subdirectory')) + + def test_contents(self): + contents = set(resources.contents(self.data)) + # There may be cruft in the directory listing of the data directory. + # Under Python 3 we could have a __pycache__ directory, and under + # Python 2 we could have .pyc files. These are both artifacts of the + # test suite importing these modules and writing these caches. They + # aren't germane to this test, so just filter them out. + contents.discard('__pycache__') + contents.discard('__init__.pyc') + contents.discard('__init__.pyo') + self.assertEqual(contents, { + '__init__.py', + 'subdirectory', + 'utf-8.file', + 'binary.file', + 'utf-16.file', + }) + + +class ResourceDiskTests(ResourceTests, unittest.TestCase): + def setUp(self): + self.data = data01 + + +class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase): + pass + + +class ResourceLoaderTests(unittest.TestCase): + def test_resource_contents(self): + package = util.create_package( + file=data01, path=data01.__file__, contents=['A', 'B', 'C']) + self.assertEqual( + set(resources.contents(package)), + {'A', 'B', 'C'}) + + def test_resource_is_resource(self): + package = util.create_package( + file=data01, path=data01.__file__, + contents=['A', 'B', 'C', 'D/E', 'D/F']) + self.assertTrue(resources.is_resource(package, 'B')) + + def test_resource_directory_is_not_resource(self): + package = util.create_package( + file=data01, path=data01.__file__, + contents=['A', 'B', 'C', 'D/E', 'D/F']) + self.assertFalse(resources.is_resource(package, 'D')) + + def test_resource_missing_is_not_resource(self): + package = util.create_package( + file=data01, path=data01.__file__, + contents=['A', 'B', 'C', 'D/E', 'D/F']) + self.assertFalse(resources.is_resource(package, 'Z')) + + +class ResourceCornerCaseTests(unittest.TestCase): + def test_package_has_no_reader_fallback(self): + # Test odd ball packages which: + # 1. Do not have a ResourceReader as a loader + # 2. Are not on the file system + # 3. Are not in a zip file + module = util.create_package( + file=data01, path=data01.__file__, contents=['A', 'B', 'C']) + # Give the module a dummy loader. + module.__loader__ = object() + # Give the module a dummy origin. + module.__file__ = '/path/which/shall/not/be/named' + if sys.version_info >= (3,): + module.__spec__.loader = module.__loader__ + module.__spec__.origin = module.__file__ + self.assertFalse(resources.is_resource(module, 'A')) + + +class ResourceFromZipsTest(util.ZipSetupBase, unittest.TestCase): + ZIP_MODULE = zipdata02 # type: ignore + + def test_unrelated_contents(self): + # https://gitlab.com/python-devs/importlib_resources/issues/44 + # + # Here we have a zip file with two unrelated subpackages. The bug + # reports that getting the contents of a resource returns unrelated + # files. + self.assertEqual( + set(resources.contents('ziptestdata.one')), + {'__init__.py', 'resource1.txt'}) + self.assertEqual( + set(resources.contents('ziptestdata.two')), + {'__init__.py', 'resource2.txt'}) + + +class NamespaceTest(unittest.TestCase): + def test_namespaces_cant_have_resources(self): + contents = set(resources.contents( + 'test.test_importlib.data03.namespace')) + self.assertEqual(len(contents), 0) + # Even though there is a file in the namespace directory, it is not + # considered a resource, since namespace packages can't have them. + self.assertFalse(resources.is_resource( + 'test.test_importlib.data03.namespace', + 'resource1.txt')) + # We should get an exception if we try to read it or open it. + self.assertRaises( + FileNotFoundError, + resources.open_text, + 'test.test_importlib.data03.namespace', 'resource1.txt') + self.assertRaises( + FileNotFoundError, + resources.open_binary, + 'test.test_importlib.data03.namespace', 'resource1.txt') + self.assertRaises( + FileNotFoundError, + resources.read_text, + 'test.test_importlib.data03.namespace', 'resource1.txt') + self.assertRaises( + FileNotFoundError, + resources.read_binary, + 'test.test_importlib.data03.namespace', 'resource1.txt') + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index 64e039e00fe..bfb7cad6e59 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -1,17 +1,24 @@ +import abc import builtins import contextlib import errno import functools import importlib from importlib import machinery, util, invalidate_caches +from importlib.abc import ResourceReader +import io import os import os.path +from pathlib import Path, PurePath from test import support import unittest import sys import tempfile import types +from . import data01 +from . import zipdata01 + BUILTINS = types.SimpleNamespace() BUILTINS.good_name = None @@ -386,3 +393,159 @@ def caseok_env_changed(self, *, should_exist): if any(x in self.importlib._bootstrap_external._os.environ for x in possibilities) != should_exist: self.skipTest('os.environ changes not reflected in _os.environ') + + +def create_package(file, path, is_package=True, contents=()): + class Reader(ResourceReader): + def open_resource(self, path): + self._path = path + if isinstance(file, Exception): + raise file + else: + return file + + def resource_path(self, path_): + self._path = path_ + if isinstance(path, Exception): + raise path + else: + return path + + def is_resource(self, path_): + self._path = path_ + if isinstance(path, Exception): + raise path + for entry in contents: + parts = entry.split('/') + if len(parts) == 1 and parts[0] == path_: + return True + return False + + def contents(self): + if isinstance(path, Exception): + raise path + # There's no yield from in baseball, er, Python 2. + for entry in contents: + yield entry + + name = 'testingpackage' + # Unforunately importlib.util.module_from_spec() was not introduced until + # Python 3.5. + module = types.ModuleType(name) + loader = Reader() + spec = machinery.ModuleSpec( + name, loader, + origin='does-not-exist', + is_package=is_package) + module.__spec__ = spec + module.__loader__ = loader + return module + + +class CommonResourceTests(abc.ABC): + @abc.abstractmethod + def execute(self, package, path): + raise NotImplementedError + + def test_package_name(self): + # Passing in the package name should succeed. + self.execute(data01.__name__, 'utf-8.file') + + def test_package_object(self): + # Passing in the package itself should succeed. + self.execute(data01, 'utf-8.file') + + def test_string_path(self): + # Passing in a string for the path should succeed. + path = 'utf-8.file' + self.execute(data01, path) + + @unittest.skipIf(sys.version_info < (3, 6), 'requires os.PathLike support') + def test_pathlib_path(self): + # Passing in a pathlib.PurePath object for the path should succeed. + path = PurePath('utf-8.file') + self.execute(data01, path) + + def test_absolute_path(self): + # An absolute path is a ValueError. + path = Path(__file__) + full_path = path.parent/'utf-8.file' + with self.assertRaises(ValueError): + self.execute(data01, full_path) + + def test_relative_path(self): + # A reative path is a ValueError. + with self.assertRaises(ValueError): + self.execute(data01, '../data01/utf-8.file') + + def test_importing_module_as_side_effect(self): + # The anchor package can already be imported. + del sys.modules[data01.__name__] + self.execute(data01.__name__, 'utf-8.file') + + def test_non_package_by_name(self): + # The anchor package cannot be a module. + with self.assertRaises(TypeError): + self.execute(__name__, 'utf-8.file') + + def test_non_package_by_package(self): + # The anchor package cannot be a module. + with self.assertRaises(TypeError): + module = sys.modules['test.test_importlib.util'] + self.execute(module, 'utf-8.file') + + @unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2') + def test_resource_opener(self): + bytes_data = io.BytesIO(b'Hello, world!') + package = create_package(file=bytes_data, path=FileNotFoundError()) + self.execute(package, 'utf-8.file') + self.assertEqual(package.__loader__._path, 'utf-8.file') + + @unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2') + def test_resource_path(self): + bytes_data = io.BytesIO(b'Hello, world!') + path = __file__ + package = create_package(file=bytes_data, path=path) + self.execute(package, 'utf-8.file') + self.assertEqual(package.__loader__._path, 'utf-8.file') + + def test_useless_loader(self): + package = create_package(file=FileNotFoundError(), + path=FileNotFoundError()) + with self.assertRaises(FileNotFoundError): + self.execute(package, 'utf-8.file') + + +class ZipSetupBase: + ZIP_MODULE = None + + @classmethod + def setUpClass(cls): + data_path = Path(cls.ZIP_MODULE.__file__) + data_dir = data_path.parent + cls._zip_path = str(data_dir / 'ziptestdata.zip') + sys.path.append(cls._zip_path) + cls.data = importlib.import_module('ziptestdata') + + @classmethod + def tearDownClass(cls): + try: + sys.path.remove(cls._zip_path) + except ValueError: + pass + + try: + del sys.path_importer_cache[cls._zip_path] + del sys.modules[cls.data.__name__] + except KeyError: + pass + + try: + del cls.data + del cls._zip_path + except AttributeError: + pass + + +class ZipSetup(ZipSetupBase): + ZIP_MODULE = zipdata01 # type: ignore diff --git a/Lib/test/test_importlib/zipdata01/__init__.py b/Lib/test/test_importlib/zipdata01/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/zipdata01/ziptestdata.zip b/Lib/test/test_importlib/zipdata01/ziptestdata.zip new file mode 100644 index 00000000000..8d8fa97f199 Binary files /dev/null and b/Lib/test/test_importlib/zipdata01/ziptestdata.zip differ diff --git a/Lib/test/test_importlib/zipdata02/__init__.py b/Lib/test/test_importlib/zipdata02/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Lib/test/test_importlib/zipdata02/ziptestdata.zip b/Lib/test/test_importlib/zipdata02/ziptestdata.zip new file mode 100644 index 00000000000..6f348899a80 Binary files /dev/null and b/Lib/test/test_importlib/zipdata02/ziptestdata.zip differ diff --git a/Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst b/Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst index f77cdb03dde..02b7e5fef11 100644 --- a/Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst +++ b/Misc/NEWS.d/next/Library/2017-12-15-15-34-12.bpo-32248.zmO8G2.rst @@ -1,2 +1,3 @@ Add :class:`importlib.abc.ResourceReader` as an ABC for loaders to provide a -unified API for reading resources contained within packages. +unified API for reading resources contained within packages. Also add +:mod:`importlib.resources` as the port of ``importlib_resources``. From webhook-mailer at python.org Sat Dec 30 15:40:23 2017 From: webhook-mailer at python.org (Yury Selivanov) Date: Sat, 30 Dec 2017 20:40:23 -0000 Subject: [Python-checkins] bpo-32458: Temporarily mask start-tls proactor test on Windows (#5054) Message-ID: https://github.com/python/cpython/commit/0c36bed1c46d07ef91d3e02e69e974e4f3ecd31a commit: 0c36bed1c46d07ef91d3e02e69e974e4f3ecd31a branch: master author: Yury Selivanov committer: GitHub date: 2017-12-30T15:40:20-05:00 summary: bpo-32458: Temporarily mask start-tls proactor test on Windows (#5054) files: M Lib/test/test_asyncio/test_sslproto.py diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 886c5cf3626..475f494b670 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -1,5 +1,6 @@ """Tests for asyncio/sslproto.py.""" +import os import logging import unittest from unittest import mock @@ -296,7 +297,7 @@ def test_start_tls_wrong_args(self): @unittest.skipIf(ssl is None, 'No ssl module') -class SelectorStartTLS(BaseStartTLS, unittest.TestCase): +class SelectorStartTLSTests(BaseStartTLS, unittest.TestCase): def new_loop(self): return asyncio.SelectorEventLoop() @@ -304,7 +305,8 @@ def new_loop(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') -class ProactorStartTLS(BaseStartTLS, unittest.TestCase): + at unittest.skipIf(os.environ.get('APPVEYOR'), 'XXX: issue 32458') +class ProactorStartTLSTests(BaseStartTLS, unittest.TestCase): def new_loop(self): return asyncio.ProactorEventLoop() From webhook-mailer at python.org Sat Dec 30 16:39:24 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Sat, 30 Dec 2017 21:39:24 -0000 Subject: [Python-checkins] bpo-32399: Starting with AIX6.1 there is support in libc.a for uuid (RFC4122) (#4974) Message-ID: https://github.com/python/cpython/commit/0d3ccb4395cccb11a50289c84c9a0dbbac03c647 commit: 0d3ccb4395cccb11a50289c84c9a0dbbac03c647 branch: master author: Michael Felt committer: Antoine Pitrou date: 2017-12-30T22:39:20+01:00 summary: bpo-32399: Starting with AIX6.1 there is support in libc.a for uuid (RFC4122) (#4974) Starting with AIX6.1 there is support in libc.a for uuid (RFC4122) This patch provides the changes needed for this integration with the OS. On AIX the base function is uuid_create() rather than uuid_generate_time() The AIX uuid_t typedef is more aligned to the UUID field based definition while the Linux typedef that is more aligned with UUID bytes (or perhaps UUID bytes_le) definitions. files: A Misc/NEWS.d/next/Core and Builtins/2017-12-22-13-38-17.bpo-32399.wlH12z.rst M Modules/_uuidmodule.c M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-22-13-38-17.bpo-32399.wlH12z.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-22-13-38-17.bpo-32399.wlH12z.rst new file mode 100644 index 00000000000..ab18f268c81 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-22-13-38-17.bpo-32399.wlH12z.rst @@ -0,0 +1 @@ +Add AIX uuid library support for RFC4122 using uuid_create() in libc.a diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c index d4bc3c7b0d4..1b37511c228 100644 --- a/Modules/_uuidmodule.c +++ b/Modules/_uuidmodule.c @@ -1,22 +1,33 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#ifdef HAVE_UUID_UUID_H #include +#endif +#ifdef HAVE_UUID_H +#include +#endif static PyObject * py_uuid_generate_time_safe(void) { + uuid_t uuid; #ifdef HAVE_UUID_GENERATE_TIME_SAFE - uuid_t out; int res; - res = uuid_generate_time_safe(out); - return Py_BuildValue("y#i", (const char *) out, sizeof(out), res); + res = uuid_generate_time_safe(uuid); + return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res); +#elif HAVE_UUID_CREATE +/* + * AIX support for uuid - RFC4122 + */ + unsigned32 status; + uuid_create(&uuid, &status); + return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status); #else - uuid_t out; - uuid_generate_time(out); - return Py_BuildValue("y#O", (const char *) out, sizeof(out), Py_None); + uuid_generate_time(uuid); + return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None); #endif } diff --git a/configure b/configure index 2728f67b577..da2c43fe7a2 100755 --- a/configure +++ b/configure @@ -9516,6 +9516,21 @@ _ACEOF fi # Dynamic linking for HP-UX +# checks for uuid.h location +for ac_header in uuid/uuid.h uuid.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe" >&5 $as_echo_n "checking for uuid_generate_time_safe... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9546,6 +9561,37 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RFC4122 - uuid support on AIX" >&5 +$as_echo_n "checking for RFC4122 - uuid support on AIX... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef uuid_create +void *x = uuid_create +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_UUID_CREATE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux diff --git a/configure.ac b/configure.ac index 027109c65d2..9a84e90e34c 100644 --- a/configure.ac +++ b/configure.ac @@ -2681,6 +2681,9 @@ AC_CHECK_LIB(sendfile, sendfile) AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX +# checks for uuid.h location +AC_CHECK_HEADERS([uuid/uuid.h uuid.h]) + AC_MSG_CHECKING(for uuid_generate_time_safe) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #ifndef uuid_generate_time_safe @@ -2692,6 +2695,18 @@ void *x = uuid_generate_time_safe [AC_MSG_RESULT(no)] ) +# AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) +AC_MSG_CHECKING(for RFC4122 - uuid support on AIX) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ +#ifndef uuid_create +void *x = uuid_create +#endif +]])], + [AC_DEFINE(HAVE_UUID_CREATE, 1, Define if uuid_create() exists. AIX support for uuid:RFC4122) + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)] +) + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux diff --git a/pyconfig.h.in b/pyconfig.h.in index d828d48af8c..4cf2f035c23 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1191,9 +1191,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H +/* Define if uuid_create() exists. AIX support for uuid:RFC4122 */ +#undef HAVE_UUID_CREATE + /* Define if uuid_generate_time_safe() exists. */ #undef HAVE_UUID_GENERATE_TIME_SAFE +/* Define to 1 if you have the header file. */ +#undef HAVE_UUID_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UUID_UUID_H + /* Define to 1 if you have the `wait3' function. */ #undef HAVE_WAIT3 From webhook-mailer at python.org Sat Dec 30 18:17:39 2017 From: webhook-mailer at python.org (Zachary Ware) Date: Sat, 30 Dec 2017 23:17:39 -0000 Subject: [Python-checkins] Add missing backslashes in PCbuild bat files (GH-5056) Message-ID: https://github.com/python/cpython/commit/6c6d3a46087bacb9c767c8cf2185505348d3796d commit: 6c6d3a46087bacb9c767c8cf2185505348d3796d branch: master author: Zachary Ware committer: GitHub date: 2017-12-30T17:17:36-06:00 summary: Add missing backslashes in PCbuild bat files (GH-5056) files: M PCbuild/get_externals.bat M PCbuild/prepare_ssl.bat M PCbuild/prepare_tcltk.bat diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 298bd9faafc..ed9ff759a37 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -39,7 +39,7 @@ if "%DO_FETCH%"=="false" goto end :fetch if "%ORG%"=="" (set ORG=python) -call "%PCBUILD%find_python.bat" "%PYTHON%" +call "%PCBUILD%\find_python.bat" "%PYTHON%" if "%PYTHON%"=="" ( where /Q git || echo Python 3.6 could not be found or installed, and git.exe is not on your PATH && exit /B 1 @@ -65,7 +65,7 @@ for %%e in (%libraries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-source-deps --branch %%e "%EXTERNALS_DIR%\%%e" ) else ( echo.Fetching %%e... - %PYTHON% "%PCBUILD%get_external.py" -O %ORG% %%e + %PYTHON% "%PCBUILD%\get_external.py" -O %ORG% %%e ) ) @@ -84,7 +84,7 @@ for %%b in (%binaries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-bin-deps --branch %%b "%EXTERNALS_DIR%\%%b" ) else ( echo.Fetching %%b... - %PYTHON% "%PCBUILD%get_external.py" -b -O %ORG% %%b + %PYTHON% "%PCBUILD%\get_external.py" -b -O %ORG% %%b ) ) diff --git a/PCbuild/prepare_ssl.bat b/PCbuild/prepare_ssl.bat index 5a3de2d8ac8..bfdac540442 100644 --- a/PCbuild/prepare_ssl.bat +++ b/PCbuild/prepare_ssl.bat @@ -45,19 +45,19 @@ goto Usage if not defined SRC (echo --in directory is required & exit /b 1) if not defined OUT (echo --out directory is required & exit /b 1) -call "%PCBUILD%find_msbuild.bat" %MSBUILD% +call "%PCBUILD%\find_msbuild.bat" %MSBUILD% if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable & exit /b 2) -call "%PCBUILD%find_python.bat" "%PYTHON%" +call "%PCBUILD%\find_python.bat" "%PYTHON%" if ERRORLEVEL 1 (echo Cannot locate python.exe on PATH or as PYTHON variable & exit /b 3) -call "%PCBUILD%get_externals.bat" --openssl-src %ORG_SETTING% +call "%PCBUILD%\get_externals.bat" --openssl-src %ORG_SETTING% if "%PERL%" == "" where perl > "%TEMP%\perl.loc" 2> nul && set /P PERL= <"%TEMP%\perl.loc" & del "%TEMP%\perl.loc" if "%PERL%" == "" (echo Cannot locate perl.exe on PATH or as PERL variable & exit /b 4) -%MSBUILD% "%PCBUILD%openssl.vcxproj" /p:Configuration=Release /p:Platform=Win32 +%MSBUILD% "%PCBUILD%\openssl.vcxproj" /p:Configuration=Release /p:Platform=Win32 if errorlevel 1 exit /b -%MSBUILD% "%PCBUILD%openssl.vcxproj" /p:Configuration=Release /p:Platform=x64 +%MSBUILD% "%PCBUILD%\openssl.vcxproj" /p:Configuration=Release /p:Platform=x64 if errorlevel 1 exit /b diff --git a/PCbuild/prepare_tcltk.bat b/PCbuild/prepare_tcltk.bat index 7e6d43e9949..77075af94f2 100644 --- a/PCbuild/prepare_tcltk.bat +++ b/PCbuild/prepare_tcltk.bat @@ -38,18 +38,18 @@ echo Unrecognized option: %1 goto Usage :Build -call "%PCBUILD%find_msbuild.bat" %MSBUILD% +call "%PCBUILD%\find_msbuild.bat" %MSBUILD% if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable & exit /b 2) -rem call "%PCBUILD%find_python.bat" "%PYTHON%" +rem call "%PCBUILD%\find_python.bat" "%PYTHON%" rem if ERRORLEVEL 1 (echo Cannot locate python.exe on PATH or as PYTHON variable & exit /b 3) -call "%PCBUILD%get_externals.bat" --tkinter-src %ORG_SETTING% +call "%PCBUILD%\get_externals.bat" --tkinter-src %ORG_SETTING% -%MSBUILD% "%PCBUILD%tcl.vcxproj" /p:Configuration=Release /p:Platform=Win32 -%MSBUILD% "%PCBUILD%tk.vcxproj" /p:Configuration=Release /p:Platform=Win32 -%MSBUILD% "%PCBUILD%tix.vcxproj" /p:Configuration=Release /p:Platform=Win32 +%MSBUILD% "%PCBUILD%\tcl.vcxproj" /p:Configuration=Release /p:Platform=Win32 +%MSBUILD% "%PCBUILD%\tk.vcxproj" /p:Configuration=Release /p:Platform=Win32 +%MSBUILD% "%PCBUILD%\tix.vcxproj" /p:Configuration=Release /p:Platform=Win32 -%MSBUILD% "%PCBUILD%tcl.vcxproj" /p:Configuration=Release /p:Platform=x64 -%MSBUILD% "%PCBUILD%tk.vcxproj" /p:Configuration=Release /p:Platform=x64 -%MSBUILD% "%PCBUILD%tix.vcxproj" /p:Configuration=Release /p:Platform=x64 +%MSBUILD% "%PCBUILD%\tcl.vcxproj" /p:Configuration=Release /p:Platform=x64 +%MSBUILD% "%PCBUILD%\tk.vcxproj" /p:Configuration=Release /p:Platform=x64 +%MSBUILD% "%PCBUILD%\tix.vcxproj" /p:Configuration=Release /p:Platform=x64 From webhook-mailer at python.org Sat Dec 30 18:54:37 2017 From: webhook-mailer at python.org (Zachary Ware) Date: Sat, 30 Dec 2017 23:54:37 -0000 Subject: [Python-checkins] Add missing backslashes in PCbuild bat files (GH-5056) (GH-5057) Message-ID: https://github.com/python/cpython/commit/fe90efdc07ec70fd4ff28eac179448a41379cff1 commit: fe90efdc07ec70fd4ff28eac179448a41379cff1 branch: 3.6 author: Zachary Ware committer: GitHub date: 2017-12-30T17:54:31-06:00 summary: Add missing backslashes in PCbuild bat files (GH-5056) (GH-5057) (cherry picked from commit 6c6d3a46087bacb9c767c8cf2185505348d3796d) files: M PCbuild/get_externals.bat diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index e6faab14de7..58e6c5de2ba 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -31,7 +31,7 @@ if "%DO_FETCH%"=="false" goto end if "%ORG%"=="" (set ORG=python) -call "%PCBUILD%find_python.bat" "%PYTHON%" +call "%PCBUILD%\find_python.bat" "%PYTHON%" if "%PYTHON%"=="" ( where /Q git || echo Python 3.6 could not be found or installed, and git.exe is not on your PATH && exit /B 1 @@ -56,7 +56,7 @@ for %%e in (%libraries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-source-deps --branch %%e "%EXTERNALS_DIR%\%%e" ) else ( echo.Fetching %%e... - %PYTHON% "%PCBUILD%get_external.py" -O %ORG% %%e + %PYTHON% "%PCBUILD%\get_external.py" -O %ORG% %%e ) ) @@ -74,7 +74,7 @@ for %%b in (%binaries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-bin-deps --branch %%b "%EXTERNALS_DIR%\%%b" ) else ( echo.Fetching %%b... - %PYTHON% "%PCBUILD%get_external.py" -b -O %ORG% %%b + %PYTHON% "%PCBUILD%\get_external.py" -b -O %ORG% %%b ) ) From webhook-mailer at python.org Sat Dec 30 19:34:50 2017 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 31 Dec 2017 00:34:50 -0000 Subject: [Python-checkins] [2.7] Add missing backslashes in PCbuild bat files (GH-5056) (GH-5058) Message-ID: https://github.com/python/cpython/commit/4be7420d7c2de105e48e494d13a7a074bb3f04c9 commit: 4be7420d7c2de105e48e494d13a7a074bb3f04c9 branch: 2.7 author: Zachary Ware committer: GitHub date: 2017-12-30T18:34:46-06:00 summary: [2.7] Add missing backslashes in PCbuild bat files (GH-5056) (GH-5058) (cherry picked from commit fe90efdc07ec70fd4ff28eac179448a41379cff1) files: M PCbuild/get_externals.bat diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index a28648a1c4a..39041f59f3e 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -30,7 +30,7 @@ if "%DO_FETCH%"=="false" goto end :fetch if "%ORG%"=="" (set ORG=python) -call "%PCBUILD%find_python.bat" "%PYTHON%" +call "%PCBUILD%\find_python.bat" "%PYTHON%" git 2>&1 > nul if ERRORLEVEL 9009 ( @@ -61,7 +61,7 @@ for %%e in (%libraries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-source-deps --branch %%e "%EXTERNALS_DIR%\%%e" ) else ( echo.Fetching %%e... - %PYTHON% "%PCBUILD%get_external.py" -O %ORG% %%e + %PYTHON% "%PCBUILD%\get_external.py" -O %ORG% %%e ) ) @@ -79,7 +79,7 @@ for %%b in (%binaries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-bin-deps --branch %%b "%EXTERNALS_DIR%\%%b" ) else ( echo.Fetching %%b... - %PYTHON% "%PCBUILD%get_external.py" -b -O %ORG% %%b + %PYTHON% "%PCBUILD%\get_external.py" -b -O %ORG% %%b ) ) From solipsis at pitrou.net Sun Dec 31 04:16:19 2017 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 31 Dec 2017 09:16:19 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20171231091619.1.AD2DDF34FDC63C29@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 1] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [0, -1, 2] memory blocks, sum=1 test_multiprocessing_spawn leaked [-2, 1, 1] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogfORFMu', '--timeout', '7200'] From webhook-mailer at python.org Sun Dec 31 13:04:17 2017 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sun, 31 Dec 2017 18:04:17 -0000 Subject: [Python-checkins] closes bpo-32460: ensure all non-static globals have initializers (#5061) Message-ID: https://github.com/python/cpython/commit/0a37a30037073a4a9ba45e560c8445048e5f2ba2 commit: 0a37a30037073a4a9ba45e560c8445048e5f2ba2 branch: master author: Benjamin Peterson committer: GitHub date: 2017-12-31T10:04:13-08:00 summary: closes bpo-32460: ensure all non-static globals have initializers (#5061) files: M Modules/_ctypes/_ctypes.c M Modules/_ctypes/_ctypes_test.c M Modules/_io/_iomodule.c M Modules/_sqlite/microprotocols.c M Modules/_sqlite/microprotocols.h M Modules/_sqlite/module.c M Parser/myreadline.c M Python/pyhash.c M Python/pylifecycle.c diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 4440ab0d69c..93e8d8d4233 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -116,10 +116,10 @@ bytes(cdata) #endif #include "ctypes.h" -PyObject *PyExc_ArgError; +PyObject *PyExc_ArgError = NULL; /* This dict maps ctypes types to POINTER types */ -PyObject *_ctypes_ptrtype_cache; +PyObject *_ctypes_ptrtype_cache = NULL; static PyTypeObject Simple_Type; diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index 2255e573393..620a3c6aea6 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -63,7 +63,7 @@ typedef struct { } TestReg; -EXPORT(TestReg) last_tfrsuv_arg; +EXPORT(TestReg) last_tfrsuv_arg = {0}; EXPORT(void) @@ -410,8 +410,8 @@ EXPORT(void) _py_func(void) { } -EXPORT(long long) last_tf_arg_s; -EXPORT(unsigned long long) last_tf_arg_u; +EXPORT(long long) last_tf_arg_s = 0; +EXPORT(unsigned long long) last_tf_arg_u = 0; struct BITS { int A: 1, B:2, C:3, D:4, E: 5, F: 6, G: 7, H: 8, I: 9; diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index f0621f4d4ab..cfd78e2d04a 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -26,33 +26,33 @@ /* Various interned strings */ -PyObject *_PyIO_str_close; -PyObject *_PyIO_str_closed; -PyObject *_PyIO_str_decode; -PyObject *_PyIO_str_encode; -PyObject *_PyIO_str_fileno; -PyObject *_PyIO_str_flush; -PyObject *_PyIO_str_getstate; -PyObject *_PyIO_str_isatty; -PyObject *_PyIO_str_newlines; -PyObject *_PyIO_str_nl; -PyObject *_PyIO_str_read; -PyObject *_PyIO_str_read1; -PyObject *_PyIO_str_readable; -PyObject *_PyIO_str_readall; -PyObject *_PyIO_str_readinto; -PyObject *_PyIO_str_readline; -PyObject *_PyIO_str_reset; -PyObject *_PyIO_str_seek; -PyObject *_PyIO_str_seekable; -PyObject *_PyIO_str_setstate; -PyObject *_PyIO_str_tell; -PyObject *_PyIO_str_truncate; -PyObject *_PyIO_str_writable; -PyObject *_PyIO_str_write; - -PyObject *_PyIO_empty_str; -PyObject *_PyIO_empty_bytes; +PyObject *_PyIO_str_close = NULL; +PyObject *_PyIO_str_closed = NULL; +PyObject *_PyIO_str_decode = NULL; +PyObject *_PyIO_str_encode = NULL; +PyObject *_PyIO_str_fileno = NULL; +PyObject *_PyIO_str_flush = NULL; +PyObject *_PyIO_str_getstate = NULL; +PyObject *_PyIO_str_isatty = NULL; +PyObject *_PyIO_str_newlines = NULL; +PyObject *_PyIO_str_nl = NULL; +PyObject *_PyIO_str_read = NULL; +PyObject *_PyIO_str_read1 = NULL; +PyObject *_PyIO_str_readable = NULL; +PyObject *_PyIO_str_readall = NULL; +PyObject *_PyIO_str_readinto = NULL; +PyObject *_PyIO_str_readline = NULL; +PyObject *_PyIO_str_reset = NULL; +PyObject *_PyIO_str_seek = NULL; +PyObject *_PyIO_str_seekable = NULL; +PyObject *_PyIO_str_setstate = NULL; +PyObject *_PyIO_str_tell = NULL; +PyObject *_PyIO_str_truncate = NULL; +PyObject *_PyIO_str_writable = NULL; +PyObject *_PyIO_str_write = NULL; + +PyObject *_PyIO_empty_str = NULL; +PyObject *_PyIO_empty_bytes = NULL; PyDoc_STRVAR(module_doc, "The io module provides the Python interfaces to stream handling. The\n" diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index 2261b8013ce..3d01872322c 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -33,7 +33,7 @@ /** the adapters registry **/ -PyObject *psyco_adapters; +static PyObject *psyco_adapters = NULL; /* pysqlite_microprotocols_init - initialize the adapters dictionary */ diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h index 6941716c4cf..99ff6f642b2 100644 --- a/Modules/_sqlite/microprotocols.h +++ b/Modules/_sqlite/microprotocols.h @@ -28,10 +28,6 @@ #include -/** adapters registry **/ - -extern PyObject *psyco_adapters; - /** the names of the three mandatory methods **/ #define MICROPROTOCOLS_GETQUOTED_NAME "getquoted" diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 9066c32db55..879c66692bc 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -35,13 +35,20 @@ /* static objects at module-level */ -PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError, - *pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError, - *pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError; - -PyObject* converters; -int _enable_callback_tracebacks; -int pysqlite_BaseTypeAdapted; +PyObject *pysqlite_Error = NULL; +PyObject *pysqlite_Warning = NULL; +PyObject *pysqlite_InterfaceError = NULL; +PyObject *pysqlite_DatabaseError = NULL; +PyObject *pysqlite_InternalError = NULL; +PyObject *pysqlite_OperationalError = NULL; +PyObject *pysqlite_ProgrammingError = NULL; +PyObject *pysqlite_IntegrityError = NULL; +PyObject *pysqlite_DataError = NULL; +PyObject *pysqlite_NotSupportedError = NULL; + +PyObject* converters = NULL; +int _enable_callback_tracebacks = 0; +int pysqlite_BaseTypeAdapted = 0; static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* kwargs) @@ -461,10 +468,6 @@ PyMODINIT_FUNC PyInit__sqlite3(void) /* initialize the default converters */ converters_init(dict); - _enable_callback_tracebacks = 0; - - pysqlite_BaseTypeAdapted = 0; - error: if (PyErr_Occurred()) { diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 7fe04a9d365..ab6bd4e8300 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -17,7 +17,7 @@ #endif /* MS_WINDOWS */ -PyThreadState* _PyOS_ReadlineTState; +PyThreadState* _PyOS_ReadlineTState = NULL; #include "pythread.h" static PyThread_type_lock _PyOS_ReadlineLock = NULL; @@ -284,7 +284,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) Note: Python expects in return a buffer allocated with PyMem_Malloc. */ -char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *); +char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) = NULL; /* Interface used by tokenizer.c and bltinmodule.c */ diff --git a/Python/pyhash.c b/Python/pyhash.c index 1537a0fb490..a0850d066b3 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -17,7 +17,7 @@ extern "C" { #endif -_Py_HashSecret_t _Py_HashSecret; +_Py_HashSecret_t _Py_HashSecret = {0}; #if Py_HASH_ALGORITHM == Py_HASH_EXTERNAL extern PyHash_FuncDef PyHash_Func; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 560d0e36d49..2f61db0d826 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -108,17 +108,17 @@ _Py_IsFinalizing(void) /* Global configuration variable declarations are in pydebug.h */ /* XXX (ncoghlan): move those declarations to pylifecycle.h? */ -int Py_DebugFlag; /* Needed by parser.c */ -int Py_VerboseFlag; /* Needed by import.c */ -int Py_QuietFlag; /* Needed by sysmodule.c */ -int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ -int Py_InspectFlag; /* Needed to determine whether to exit at SystemExit */ +int Py_DebugFlag = 0; /* Needed by parser.c */ +int Py_VerboseFlag = 0; /* Needed by import.c */ +int Py_QuietFlag = 0; /* Needed by sysmodule.c */ +int Py_InteractiveFlag = 0; /* Needed by Py_FdIsInteractive() below */ +int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */ int Py_OptimizeFlag = 0; /* Needed by compile.c */ -int Py_NoSiteFlag; /* Suppress 'import site' */ -int Py_BytesWarningFlag; /* Warn on str(bytes) and str(buffer) */ -int Py_FrozenFlag; /* Needed by getpath.c */ -int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */ -int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.pyc) */ +int Py_NoSiteFlag = 0; /* Suppress 'import site' */ +int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */ +int Py_FrozenFlag = 0; /* Needed by getpath.c */ +int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */ +int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */ int Py_NoUserSiteDirectory = 0; /* for -s and site.py */ int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */ int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */ From webhook-mailer at python.org Sun Dec 31 16:35:25 2017 From: webhook-mailer at python.org (Antoine Pitrou) Date: Sun, 31 Dec 2017 21:35:25 -0000 Subject: [Python-checkins] bpo-32468: Better frame repr() (#5067) Message-ID: https://github.com/python/cpython/commit/14709144b521b9916f798a43aac9dc44fd44f6ca commit: 14709144b521b9916f798a43aac9dc44fd44f6ca branch: master author: Antoine Pitrou committer: GitHub date: 2017-12-31T22:35:22+01:00 summary: bpo-32468: Better frame repr() (#5067) bpo-32468: Better frame repr() files: A Misc/NEWS.d/next/Library/2017-12-31-20-32-58.bpo-32468.YBs__0.rst M Lib/test/test_frame.py M Objects/frameobject.c diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index cabfef236dd..fd795085a5c 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -1,3 +1,4 @@ +import re import types import unittest import weakref @@ -159,5 +160,45 @@ def test_locals_clear_locals(self): self.assertEqual(inner.f_locals, {}) +class ReprTest(unittest.TestCase): + """ + Tests for repr(frame). + """ + + def test_repr(self): + def outer(): + x = 5 + y = 6 + def inner(): + z = x + 2 + 1/0 + t = 9 + return inner() + + offset = outer.__code__.co_firstlineno + try: + outer() + except ZeroDivisionError as e: + tb = e.__traceback__ + frames = [] + while tb: + frames.append(tb.tb_frame) + tb = tb.tb_next + else: + self.fail("should have raised") + + f_this, f_outer, f_inner = frames + file_repr = re.escape(repr(__file__)) + self.assertRegex(repr(f_this), + r"^$" + % (file_repr, offset + 23)) + self.assertRegex(repr(f_outer), + r"^$" + % (file_repr, offset + 7)) + self.assertRegex(repr(f_inner), + r"^$" + % (file_repr, offset + 5)) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-12-31-20-32-58.bpo-32468.YBs__0.rst b/Misc/NEWS.d/next/Library/2017-12-31-20-32-58.bpo-32468.YBs__0.rst new file mode 100644 index 00000000000..135bbd816e8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-31-20-32-58.bpo-32468.YBs__0.rst @@ -0,0 +1 @@ +Improve frame repr() to mention filename, code name and current line number. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 6ab3a22950a..1ac3d752575 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -547,6 +547,15 @@ frame_sizeof(PyFrameObject *f) PyDoc_STRVAR(sizeof__doc__, "F.__sizeof__() -> size of F in memory, in bytes"); +static PyObject * +frame_repr(PyFrameObject *f) +{ + int lineno = PyFrame_GetLineNumber(f); + return PyUnicode_FromFormat( + "", + f, f->f_code->co_filename, lineno, f->f_code->co_name); +} + static PyMethodDef frame_methods[] = { {"clear", (PyCFunction)frame_clear, METH_NOARGS, clear__doc__}, @@ -565,7 +574,7 @@ PyTypeObject PyFrame_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)frame_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */